File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / istgt / src / istgt.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:42:02 2012 UTC (12 years, 5 months ago) by misho
Branches: istgt, MAIN
CVS tags: v20111008, HEAD
istgt

    1: /*
    2:  * Copyright (C) 2008-2011 Daisuke Aoyama <aoyama@peach.ne.jp>.
    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 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 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: #ifdef HAVE_CONFIG_H
   29: #include "config.h"
   30: #endif
   31: 
   32: #include <inttypes.h>
   33: #include <stdint.h>
   34: 
   35: #include <errno.h>
   36: #include <stdarg.h>
   37: #include <stdio.h>
   38: #include <stdlib.h>
   39: #include <string.h>
   40: #include <poll.h>
   41: #include <pthread.h>
   42: #ifdef HAVE_PTHREAD_NP_H
   43: #include <pthread_np.h>
   44: #endif
   45: #include <fcntl.h>
   46: #include <unistd.h>
   47: #include <signal.h>
   48: 
   49: #include <sys/types.h>
   50: #include <sys/socket.h>
   51: #include <netinet/in.h>
   52: 
   53: #include "istgt.h"
   54: #include "istgt_ver.h"
   55: #include "istgt_log.h"
   56: #include "istgt_conf.h"
   57: #include "istgt_sock.h"
   58: #include "istgt_misc.h"
   59: #include "istgt_crc32c.h"
   60: #include "istgt_iscsi.h"
   61: #include "istgt_lu.h"
   62: #include "istgt_proto.h"
   63: 
   64: #ifdef ISTGT_USE_KQUEUE
   65: #include <sys/types.h>
   66: #include <sys/event.h>
   67: #include <sys/time.h>
   68: #endif
   69: 
   70: #define POLLWAIT 3000
   71: #define PORTNUMLEN 32
   72: 
   73: ISTGT g_istgt;
   74: 
   75: #if 0
   76: void
   77: fatal(const char *msg, ...)
   78: {
   79: 	va_list ap;
   80: 	va_start(ap, msg);
   81: 	vfprintf(stderr, msg, ap);
   82: 	va_end(ap);
   83: 	exit(EXIT_FAILURE);
   84: }
   85: #endif
   86: 
   87: static int
   88: istgt_parse_portal(const char *portal, char **host, char **port)
   89: {
   90: 	const char *p;
   91: 	int n;
   92: 
   93: 	if (portal == NULL) {
   94: 		ISTGT_ERRLOG("portal error\n");
   95: 		return -1;
   96: 	}
   97: 
   98: 	if (portal[0] == '[') {
   99: 		/* IPv6 */
  100: 		p = strchr(portal + 1, ']');
  101: 		if (p == NULL) {
  102: 			ISTGT_ERRLOG("portal error\n");
  103: 			return -1;
  104: 		}
  105: #if 0
  106: 		n = p - (portal + 1);
  107: 		*host = xmalloc(n + 1);
  108: 		memcpy(*host, portal + 1, n);
  109: 		(*host)[n] = '\0';
  110: 		p++;
  111: #else
  112: 		p++;
  113: 		n = p - portal;
  114: 		*host = xmalloc(n + 1);
  115: 		memcpy(*host, portal, n);
  116: 		(*host)[n] = '\0';
  117: #endif
  118: 		if (p[0] == '\0') {
  119: 			*port = xmalloc(PORTNUMLEN);
  120: 			snprintf(*port, PORTNUMLEN, "%d", DEFAULT_PORT);
  121: 		} else {
  122: 			if (p[0] != ':') {
  123: 				ISTGT_ERRLOG("portal error\n");
  124: 				xfree(*host);
  125: 				return -1;
  126: 			}
  127: 			*port = xstrdup(p + 1);
  128: 		}
  129: 	} else {
  130: 		/* IPv4 */
  131: 		p = strchr(portal, ':');
  132: 		if (p == NULL) {
  133: 			p = portal + strlen(portal);
  134: 		}
  135: 		n = p - portal;
  136: 		*host = xmalloc(n + 1);
  137: 		memcpy(*host, portal, n);
  138: 		(*host)[n] = '\0';
  139: 		if (p[0] == '\0') {
  140: 			*port = xmalloc(PORTNUMLEN);
  141: 			snprintf(*port, PORTNUMLEN, "%d", DEFAULT_PORT);
  142: 		} else {
  143: 			if (p[0] != ':') {
  144: 				ISTGT_ERRLOG("portal error\n");
  145: 				xfree(*host);
  146: 				return -1;
  147: 			}
  148: 			*port = xstrdup(p + 1);
  149: 		}
  150: 	}
  151: 	return 0;
  152: }
  153: 
  154: static int
  155: istgt_add_portal(ISTGT_Ptr istgt, CF_SECTION *sp, int idx1)
  156: {
  157: 	char *label, *portal, *host, *port;
  158: 	int idx;
  159: 	int rc;
  160: 
  161: 	label = istgt_get_nmval(sp, "Portal", idx1, 0);
  162: 	portal = istgt_get_nmval(sp, "Portal", idx1, 1);
  163: 	if (label == NULL || portal == NULL) {
  164: 		ISTGT_ERRLOG("portal error\n");
  165: 		return -1;
  166: 	}
  167: 
  168: 	rc = istgt_parse_portal(portal, &host, &port);
  169: 	if (rc < 0) {
  170: 		ISTGT_ERRLOG("parse portal error\n");
  171: 		return -1;
  172: 	}
  173: 
  174: 	idx = istgt->nportal;
  175: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  176: 	    "Index=%d, Host=%s, Port=%s, Tag=%d\n",
  177: 	    idx, host, port, sp->num);
  178: 	if (idx < MAX_PORTAL) {
  179: 		istgt->portal[idx].label = xstrdup(label);
  180: 		istgt->portal[idx].host = host;
  181: 		istgt->portal[idx].port = port;
  182: 		istgt->portal[idx].idx = idx;
  183: 		istgt->portal[idx].tag = sp->num;
  184: 		istgt->portal[idx].sock = -1;
  185: 		idx++;
  186: 		istgt->nportal = idx;
  187: 	} else {
  188: 		ISTGT_ERRLOG("nportal(%d) >= MAX_PORTAL\n", idx);
  189: 		xfree(host);
  190: 		xfree(port);
  191: 		return -1;
  192: 	}
  193: 	return 0;
  194: }
  195: 
  196: static int
  197: istgt_build_portal_array(ISTGT_Ptr istgt)
  198: {
  199: 	CF_SECTION *sp;
  200: 	const char *val;
  201: 	int rc;
  202: 	int i;
  203: 
  204: 	sp = istgt->config->section;
  205: 	while (sp != NULL) {
  206: 		if (sp->type == ST_PORTALGROUP) {
  207: 			if (sp->num == 0) {
  208: 				ISTGT_ERRLOG("Group 0 is invalid\n");
  209: 				return -1;
  210: 			}
  211: 			if (sp->num > ISTGT_PG_TAG_MAX) {
  212: 				ISTGT_ERRLOG("tag %d is invalid\n", sp->num);
  213: 				return -1;
  214: 			}
  215: 
  216: 			val = istgt_get_val(sp, "Comment");
  217: 			if (val != NULL) {
  218: 				ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  219: 				    "Comment %s\n", val);
  220: 			}
  221: 			for (i = 0; ; i++) {
  222: 				val = istgt_get_nval(sp, "Portal", i);
  223: 				if (val == NULL)
  224: 					break;
  225: 				rc = istgt_add_portal(istgt, sp, i);
  226: 				if (rc < 0) {
  227: 					ISTGT_ERRLOG("add_portal() failed\n");
  228: 					return -1;
  229: 				}
  230: 			}
  231: 		}
  232: 		sp = sp->next;
  233: 	}
  234: 	return 0;
  235: }
  236: 
  237: static void
  238: istgt_destroy_portal_array(ISTGT_Ptr istgt)
  239: {
  240: 	int i;
  241: 
  242: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_destroy_portal_array\n");
  243: 	for (i = 0; i < istgt->nportal; i++) {
  244: 		xfree(istgt->portal[i].label);
  245: 		xfree(istgt->portal[i].host);
  246: 		xfree(istgt->portal[i].port);
  247: 
  248: 		istgt->portal[i].label = NULL;
  249: 		istgt->portal[i].host = NULL;
  250: 		istgt->portal[i].port = NULL;
  251: 		istgt->portal[i].idx = i;
  252: 		istgt->portal[i].tag = 0;
  253: 	}
  254: 	istgt->nportal = 0;
  255: }
  256: 
  257: static int
  258: istgt_open_portal(ISTGT_Ptr istgt)
  259: {
  260: 	int port;
  261: 	int sock;
  262: 	int i;
  263: 
  264: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_open_portal\n");
  265: 	for (i = 0; i < istgt->nportal; i++) {
  266: 		if (istgt->portal[i].sock < 0) {
  267: 			ISTGT_TRACELOG(ISTGT_TRACE_NET,
  268: 			    "open host %s, port %s, tag %d\n",
  269: 			    istgt->portal[i].host, istgt->portal[i].port,
  270: 			    istgt->portal[i].tag);
  271: 			port = (int)strtol(istgt->portal[i].port, NULL, 0);
  272: 			sock = istgt_listen(istgt->portal[i].host, port);
  273: 			if (sock < 0) {
  274: 				ISTGT_ERRLOG("listen error %.64s:%d\n",
  275: 				    istgt->portal[i].host, port);
  276: 				return -1;
  277: 			}
  278: 			istgt->portal[i].sock = sock;
  279: 		}
  280: 	}
  281: 	return 0;
  282: }
  283: 
  284: static int
  285: istgt_close_portal(ISTGT_Ptr istgt)
  286: {
  287: 	int i;
  288: 
  289: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_close_portal\n");
  290: 	for (i = 0; i < istgt->nportal; i++) {
  291: 		if (istgt->portal[i].sock >= 0) {
  292: 			ISTGT_TRACELOG(ISTGT_TRACE_NET,
  293: 			    "close host %s, port %s, tag %d\n",
  294: 			    istgt->portal[i].host, istgt->portal[i].port,
  295: 			    istgt->portal[i].tag);
  296: 			close(istgt->portal[i].sock);
  297: 			istgt->portal[i].sock = -1;
  298: 		}
  299: 	}
  300: 	return 0;
  301: }
  302: 
  303: static int
  304: istgt_add_initiator_group(ISTGT_Ptr istgt, CF_SECTION *sp)
  305: {
  306: 	const char *val;
  307: 	int alloc_len;
  308: 	int idx;
  309: 	int names;
  310: 	int masks;
  311: 	int i;
  312: 
  313: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "add initiator group %d\n", sp->num);
  314: 
  315: 	val = istgt_get_val(sp, "Comment");
  316: 	if (val != NULL) {
  317: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Comment %s\n", val);
  318: 	}
  319: 
  320: 	/* counts number of definition */
  321: 	for (i = 0; ; i++) {
  322: 		val = istgt_get_nval(sp, "InitiatorName", i);
  323: 		if (val == NULL)
  324: 			break;
  325: 	}
  326: 	names = i;
  327: 	if (names > MAX_INITIATOR) {
  328: 		ISTGT_ERRLOG("%d > MAX_INITIATOR\n", names);
  329: 		return -1;
  330: 	}
  331: 	for (i = 0; ; i++) {
  332: 		val = istgt_get_nval(sp, "Netmask", i);
  333: 		if (val == NULL)
  334: 			break;
  335: 	}
  336: 	masks = i;
  337: 	if (masks > MAX_NETMASK) {
  338: 		ISTGT_ERRLOG("%d > MAX_NETMASK\n", masks);
  339: 		return -1;
  340: 	}
  341: 
  342: 	idx = istgt->ninitiator_group;
  343: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  344: 	    "Index=%d, Tag=%d, Names=%d, Masks=%d\n",
  345: 	    idx, sp->num, names, masks);
  346: 	if (idx < MAX_INITIATOR_GROUP) {
  347: 		istgt->initiator_group[idx].ninitiators = names;
  348: 		alloc_len = sizeof (char *) * names;
  349: 		istgt->initiator_group[idx].initiators = xmalloc(alloc_len);
  350: 		istgt->initiator_group[idx].nnetmasks = masks;
  351: 		alloc_len = sizeof (char *) * masks;
  352: 		istgt->initiator_group[idx].netmasks = xmalloc(alloc_len);
  353: 		istgt->initiator_group[idx].idx = idx;
  354: 		istgt->initiator_group[idx].tag = sp->num;
  355: 
  356: 		for (i = 0; i < names; i++) {
  357: 			val = istgt_get_nval(sp, "InitiatorName", i);
  358: 			ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  359: 			    "InitiatorName %s\n", val);
  360: 			istgt->initiator_group[idx].initiators[i] = xstrdup(val);
  361: 		}
  362: 		for (i = 0; i < masks; i++) {
  363: 			val = istgt_get_nval(sp, "Netmask", i);
  364: 			ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Netmask %s\n", val);
  365: 			istgt->initiator_group[idx].netmasks[i] = xstrdup(val);
  366: 		}
  367: 
  368: 		idx++;
  369: 		istgt->ninitiator_group = idx;
  370: 	} else {
  371: 		ISTGT_ERRLOG("ninitiator_group(%d) >= MAX_INITIATOR_GROUP\n", idx);
  372: 		return -1;
  373: 	}
  374: 	return 0;
  375: }
  376: 
  377: static int
  378: istgt_build_initiator_group_array(ISTGT_Ptr istgt)
  379: {
  380: 	CF_SECTION *sp;
  381: 	int rc;
  382: 
  383: 	sp = istgt->config->section;
  384: 	while (sp != NULL) {
  385: 		if (sp->type == ST_INITIATORGROUP) {
  386: 			if (sp->num == 0) {
  387: 				ISTGT_ERRLOG("Group 0 is invalid\n");
  388: 				return -1;
  389: 			}
  390: 			rc = istgt_add_initiator_group(istgt, sp);
  391: 			if (rc < 0) {
  392: 				ISTGT_ERRLOG("add_initiator_group() failed\n");
  393: 				return -1;
  394: 			}
  395: 		}
  396: 		sp = sp->next;
  397: 	}
  398: 	return 0;
  399: }
  400: 
  401: static void
  402: istgt_destory_initiator_group_array(ISTGT_Ptr istgt)
  403: {
  404: 	int i, j;
  405: 
  406: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_destory_initiator_group_array\n");
  407: 	for (i = 0; i < istgt->ninitiator_group; i++) {
  408: 		for (j = 0; j < istgt->initiator_group[i].ninitiators; j++) {
  409: 			xfree(istgt->initiator_group[i].initiators[j]);
  410: 		}
  411: 		xfree(istgt->initiator_group[i].initiators);
  412: 		for (j = 0; j < istgt->initiator_group[i].nnetmasks; j++) {
  413: 			xfree(istgt->initiator_group[i].netmasks[j]);
  414: 		}
  415: 		xfree(istgt->initiator_group[i].netmasks);
  416: 
  417: 		istgt->initiator_group[i].ninitiators = 0;
  418: 		istgt->initiator_group[i].initiators = NULL;
  419: 		istgt->initiator_group[i].nnetmasks = 0;
  420: 		istgt->initiator_group[i].netmasks = NULL;
  421: 		istgt->initiator_group[i].idx = i;
  422: 		istgt->initiator_group[i].tag = 0;
  423: 	}
  424: 	istgt->ninitiator_group = 0;
  425: }
  426: 
  427: static int
  428: istgt_build_uctl_portal(ISTGT_Ptr istgt)
  429: {
  430: 	CF_SECTION *sp;
  431: 	const char *val;
  432: 	char *label, *portal, *host, *port;
  433: 	int tag;
  434: 	int idx;
  435: 	int rc;
  436: 	int i;
  437: 
  438: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_build_uctl_portal\n");
  439: 
  440: 	sp = istgt_find_cf_section(istgt->config, "UnitControl");
  441: 	if (sp == NULL) {
  442: 		ISTGT_ERRLOG("find_cf_section failed()\n");
  443: 		return -1;
  444: 	}
  445: 
  446: 	for (i = 0; ; i++) {
  447: 		val = istgt_get_nval(sp, "Portal", i);
  448: 		if (val == NULL)
  449: 			break;
  450: 
  451: 		label = istgt_get_nmval(sp, "Portal", i, 0);
  452: 		portal = istgt_get_nmval(sp, "Portal", i, 1);
  453: 		if (label == NULL || portal == NULL) {
  454: 			ISTGT_ERRLOG("uctl portal error\n");
  455: 			return -1;
  456: 		}
  457: 
  458: 		rc = istgt_parse_portal(portal, &host, &port);
  459: 		if (rc < 0) {
  460: 			ISTGT_ERRLOG("parse uctl portal error\n");
  461: 			return -1;
  462: 		}
  463: 
  464: 		idx = istgt->nuctl_portal;
  465: 		tag = ISTGT_UC_TAG;
  466: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  467: 		    "Index=%d, Host=%s, Port=%s, Tag=%d\n",
  468: 		    idx, host, port, tag);
  469: 		if (idx < MAX_UCPORTAL) {
  470: 			istgt->uctl_portal[idx].label = xstrdup(label);
  471: 			istgt->uctl_portal[idx].host = host;
  472: 			istgt->uctl_portal[idx].port = port;
  473: 			istgt->uctl_portal[idx].idx = idx;
  474: 			istgt->uctl_portal[idx].tag = tag;
  475: 			istgt->uctl_portal[idx].sock = -1;
  476: 			idx++;
  477: 			istgt->nuctl_portal = idx;
  478: 		} else {
  479: 			ISTGT_ERRLOG("nportal(%d) >= MAX_UCPORTAL\n", idx);
  480: 			xfree(host);
  481: 			xfree(port);
  482: 			return -1;
  483: 		}
  484: 	}
  485: 
  486: 	return 0;
  487: }
  488: 
  489: static void
  490: istgt_destroy_uctl_portal(ISTGT_Ptr istgt)
  491: {
  492: 	int i;
  493: 
  494: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_destroy_uctl_portal\n");
  495: 	for (i = 0; i < istgt->nportal; i++) {
  496: 		xfree(istgt->uctl_portal[i].label);
  497: 		xfree(istgt->uctl_portal[i].host);
  498: 		xfree(istgt->uctl_portal[i].port);
  499: 
  500: 		istgt->uctl_portal[i].label = NULL;
  501: 		istgt->uctl_portal[i].host = NULL;
  502: 		istgt->uctl_portal[i].port = NULL;
  503: 		istgt->uctl_portal[i].idx = i;
  504: 		istgt->uctl_portal[i].tag = 0;
  505: 	}
  506: 	istgt->nuctl_portal = 0;
  507: }
  508: 
  509: static int
  510: istgt_open_uctl_portal(ISTGT_Ptr istgt)
  511: {
  512: 	int port;
  513: 	int sock;
  514: 	int i;
  515: 
  516: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_open_uctl_portal\n");
  517: 	for (i = 0; i < istgt->nuctl_portal; i++) {
  518: 		if (istgt->uctl_portal[i].sock < 0) {
  519: 			ISTGT_TRACELOG(ISTGT_TRACE_NET,
  520: 			    "open host %s, port %s, tag %d\n",
  521: 			    istgt->uctl_portal[i].host,
  522: 			    istgt->uctl_portal[i].port,
  523: 			    istgt->uctl_portal[i].tag);
  524: 			port = (int)strtol(istgt->uctl_portal[i].port, NULL, 0);
  525: 			sock = istgt_listen(istgt->uctl_portal[i].host, port);
  526: 			if (sock < 0) {
  527: 				ISTGT_ERRLOG("listen error %.64s:%d\n",
  528: 				    istgt->uctl_portal[i].host, port);
  529: 				return -1;
  530: 			}
  531: 			istgt->uctl_portal[i].sock = sock;
  532: 		}
  533: 	}
  534: 	return 0;
  535: }
  536: 
  537: static int
  538: istgt_close_uctl_portal(ISTGT_Ptr istgt)
  539: {
  540: 	int i;
  541: 
  542: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_close_uctl_portal\n");
  543: 	for (i = 0; i < istgt->nuctl_portal; i++) {
  544: 		if (istgt->uctl_portal[i].sock >= 0) {
  545: 			ISTGT_TRACELOG(ISTGT_TRACE_NET,
  546: 			    "close host %s, port %s, tag %d\n",
  547: 			    istgt->uctl_portal[i].host,
  548: 			    istgt->uctl_portal[i].port,
  549: 			    istgt->uctl_portal[i].tag);
  550: 			close(istgt->uctl_portal[i].sock);
  551: 			istgt->uctl_portal[i].sock = -1;
  552: 		}
  553: 	}
  554: 	return 0;
  555: }
  556: 
  557: static int
  558: istgt_write_pidfile(ISTGT_Ptr istgt)
  559: {
  560: 	FILE *fp;
  561: 	pid_t pid;
  562: 	int rc;
  563: 
  564: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_write_pidfile\n");
  565: 	rc = remove(istgt->pidfile);
  566: 	if (rc != 0) {
  567: 		if (errno != ENOENT) {
  568: 			ISTGT_ERRLOG("pidfile remove error %d\n", errno);
  569: 			return -1;
  570: 		}
  571: 	}
  572: 	fp = fopen(istgt->pidfile, "w");
  573: 	if (fp == NULL) {
  574: 		ISTGT_ERRLOG("pidfile open error %d\n", errno);
  575: 		return -1;
  576: 	}
  577: 	pid = getpid();
  578: 	fprintf(fp, "%d\n", (int)pid);
  579: 	fclose(fp);
  580: 	return 0;
  581: }
  582: 
  583: static void
  584: istgt_remove_pidfile(ISTGT_Ptr istgt)
  585: {
  586: 	int rc;
  587: 
  588: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_remove_pidfile\n");
  589: 	rc = remove(istgt->pidfile);
  590: 	if (rc != 0) {
  591: 		ISTGT_ERRLOG("pidfile remove error %d\n", errno);
  592: 		/* ignore error */
  593: 	}
  594: }
  595: 
  596: char *
  597: istgt_get_nmval(CF_SECTION *sp, const char *key, int idx1, int idx2)
  598: {
  599: 	CF_ITEM *ip;
  600: 	CF_VALUE *vp;
  601: 	int i;
  602: 
  603: 	ip = istgt_find_cf_nitem(sp, key, idx1);
  604: 	if (ip == NULL)
  605: 		return NULL;
  606: 	vp = ip->val;
  607: 	if (vp == NULL)
  608: 		return NULL;
  609: 	for (i = 0; vp != NULL; vp = vp->next) {
  610: 		if (i == idx2)
  611: 			return vp->value;
  612: 		i++;
  613: 	}
  614: 	return NULL;
  615: }
  616: 
  617: char *
  618: istgt_get_nval(CF_SECTION *sp, const char *key, int idx)
  619: {
  620: 	CF_ITEM *ip;
  621: 	CF_VALUE *vp;
  622: 
  623: 	ip = istgt_find_cf_nitem(sp, key, idx);
  624: 	if (ip == NULL)
  625: 		return NULL;
  626: 	vp = ip->val;
  627: 	if (vp == NULL)
  628: 		return NULL;
  629: 	return vp->value;
  630: }
  631: 
  632: char *
  633: istgt_get_val(CF_SECTION *sp, const char *key)
  634: {
  635: 	return istgt_get_nval(sp, key, 0);
  636: }
  637: 
  638: int
  639: istgt_get_nintval(CF_SECTION *sp, const char *key, int idx)
  640: {
  641: 	const char *v;
  642: 	int value;
  643: 
  644: 	v = istgt_get_nval(sp, key, idx);
  645: 	if (v == NULL)
  646: 		return -1;
  647: 	value = (int)strtol(v, NULL, 10);
  648: 	return value;
  649: }
  650: 
  651: int
  652: istgt_get_intval(CF_SECTION *sp, const char *key)
  653: {
  654: 	return istgt_get_nintval(sp, key, 0);
  655: }
  656: 
  657: static const char *
  658: istgt_get_log_facility(CONFIG *config)
  659: {
  660: 	CF_SECTION *sp;
  661: 	const char *logfacility;
  662: 
  663: 	sp = istgt_find_cf_section(config, "Global");
  664: 	if (sp == NULL) {
  665: 		return NULL;
  666: 	}
  667: 	logfacility = istgt_get_val(sp, "LogFacility");
  668: 	if (logfacility == NULL) {
  669: 		logfacility = DEFAULT_LOG_FACILITY;
  670: 	}
  671: #if 0
  672: 	if (g_trace_flag & ISTGT_TRACE_DEBUG) {
  673: 		fprintf(stderr, "LogFacility %s\n", logfacility);
  674: 	}
  675: #endif
  676: 
  677: 	return logfacility;
  678: }
  679: 
  680: static int
  681: istgt_init(ISTGT_Ptr istgt)
  682: {
  683: 	CF_SECTION *sp;
  684: 	const char *ag_tag;
  685: 	const char *val;
  686: 	size_t stacksize;
  687: 	int ag_tag_i;
  688: 	int MaxSessions;
  689: 	int MaxConnections;
  690: 	int MaxOutstandingR2T;
  691: 	int DefaultTime2Wait;
  692: 	int DefaultTime2Retain;
  693: 	int FirstBurstLength;
  694: 	int MaxBurstLength;
  695: 	int MaxRecvDataSegmentLength;
  696: 	int InitialR2T;
  697: 	int ImmediateData;
  698: 	int DataPDUInOrder;
  699: 	int DataSequenceInOrder;
  700: 	int ErrorRecoveryLevel;
  701: 	int timeout;
  702: 	int nopininterval;
  703: 	int maxr2t;
  704: 	int rc;
  705: 	int i;
  706: 
  707: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_init\n");
  708: 	sp = istgt_find_cf_section(istgt->config, "Global");
  709: 	if (sp == NULL) {
  710: 		ISTGT_ERRLOG("find_cf_section failed()\n");
  711: 		return -1;
  712: 	}
  713: 
  714: 	val = istgt_get_val(sp, "Comment");
  715: 	if (val != NULL) {
  716: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Comment %s\n", val);
  717: 	}
  718: 
  719: 	val = istgt_get_val(sp, "PidFile");
  720: 	if (val == NULL) {
  721: 		val = DEFAULT_PIDFILE;
  722: 	}
  723: 	istgt->pidfile = xstrdup(val);
  724: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "PidFile %s\n",
  725: 	    istgt->pidfile);
  726: 
  727: 	val = istgt_get_val(sp, "AuthFile");
  728: 	if (val == NULL) {
  729: 		val = DEFAULT_AUTHFILE;
  730: 	}
  731: 	istgt->authfile = xstrdup(val);
  732: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "AuthFile %s\n",
  733: 	    istgt->authfile);
  734: 
  735: #if 0
  736: 	val = istgt_get_val(sp, "MediaFile");
  737: 	if (val == NULL) {
  738: 		val = DEFAULT_MEDIAFILE;
  739: 	}
  740: 	istgt->mediafile = xstrdup(val);
  741: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MediaFile %s\n",
  742: 	    istgt->mediafile);
  743: #endif
  744: 
  745: #if 0
  746: 	val = istgt_get_val(sp, "LiveFile");
  747: 	if (val == NULL) {
  748: 		val = DEFAULT_LIVEFILE;
  749: 	}
  750: 	istgt->livefile = xstrdup(val);
  751: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LiveFile %s\n",
  752: 	    istgt->livefile);
  753: #endif
  754: 
  755: 	val = istgt_get_val(sp, "MediaDirectory");
  756: 	if (val == NULL) {
  757: 		val = DEFAULT_MEDIADIRECTORY;
  758: 	}
  759: 	istgt->mediadirectory = xstrdup(val);
  760: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MediaDirectory %s\n",
  761: 	    istgt->mediadirectory);
  762: 
  763: 	val = istgt_get_val(sp, "NodeBase");
  764: 	if (val == NULL) {
  765: 		val = DEFAULT_NODEBASE;
  766: 	}
  767: 	istgt->nodebase = xstrdup(val);
  768: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "NodeBase %s\n",
  769: 	    istgt->nodebase);
  770: 
  771: 	MaxSessions = istgt_get_intval(sp, "MaxSessions");
  772: 	if (MaxSessions < 1) {
  773: 		MaxSessions = DEFAULT_MAX_SESSIONS;
  774: 	}
  775: 	istgt->MaxSessions = MaxSessions;
  776: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxSessions %d\n",
  777: 	    istgt->MaxSessions);
  778: 
  779: 	MaxConnections = istgt_get_intval(sp, "MaxConnections");
  780: 	if (MaxConnections < 1) {
  781: 		MaxConnections = DEFAULT_MAX_CONNECTIONS;
  782: 	}
  783: 	istgt->MaxConnections = MaxConnections;
  784: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxConnections %d\n",
  785: 	    istgt->MaxConnections);
  786: 
  787: 	/* limited to 16bits - RFC3720(12.2) */
  788: 	if (MaxSessions > 0xffff) {
  789: 		ISTGT_ERRLOG("over 65535 sessions are not supported\n");
  790: 		return -1;
  791: 	}
  792: 	if (MaxConnections > 0xffff) {
  793: 		ISTGT_ERRLOG("over 65535 connections are not supported\n");
  794: 		return -1;
  795: 	}
  796: 
  797: 	MaxOutstandingR2T = istgt_get_intval(sp, "MaxOutstandingR2T");
  798: 	if (MaxOutstandingR2T < 1) {
  799: 		MaxOutstandingR2T = DEFAULT_MAXOUTSTANDINGR2T;
  800: 	}
  801: 	istgt->MaxOutstandingR2T = MaxOutstandingR2T;
  802: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxOutstandingR2T %d\n",
  803: 	    istgt->MaxOutstandingR2T);
  804: 
  805: 	DefaultTime2Wait = istgt_get_intval(sp, "DefaultTime2Wait");
  806: 	if (DefaultTime2Wait < 0) {
  807: 		DefaultTime2Wait = DEFAULT_DEFAULTTIME2WAIT;
  808: 	}
  809: 	istgt->DefaultTime2Wait = DefaultTime2Wait;
  810: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DefaultTime2Wait %d\n",
  811: 	    istgt->DefaultTime2Wait);
  812: 
  813: 	DefaultTime2Retain = istgt_get_intval(sp, "DefaultTime2Retain");
  814: 	if (DefaultTime2Retain < 0) {
  815: 		DefaultTime2Retain = DEFAULT_DEFAULTTIME2RETAIN;
  816: 	}
  817: 	istgt->DefaultTime2Retain = DefaultTime2Retain;
  818: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DefaultTime2Retain %d\n",
  819: 	    istgt->DefaultTime2Retain);
  820: 
  821: 	/* check size limit - RFC3720(12.15, 12.16, 12.17) */
  822: 	if (istgt->MaxOutstandingR2T > 65535) {
  823: 		ISTGT_ERRLOG("MaxOutstandingR2T(%d) > 65535\n",
  824: 		    istgt->MaxOutstandingR2T);
  825: 		return -1;
  826: 	}
  827: 	if (istgt->DefaultTime2Wait > 3600) {
  828: 		ISTGT_ERRLOG("DefaultTime2Wait(%d) > 3600\n",
  829: 		    istgt->DefaultTime2Wait);
  830: 		return -1;
  831: 	}
  832: 	if (istgt->DefaultTime2Retain > 3600) {
  833: 		ISTGT_ERRLOG("DefaultTime2Retain(%d) > 3600\n",
  834: 		    istgt->DefaultTime2Retain);
  835: 		return -1;
  836: 	}
  837: 
  838: 	FirstBurstLength = istgt_get_intval(sp, "FirstBurstLength");
  839: 	if (FirstBurstLength < 0) {
  840: 		FirstBurstLength = DEFAULT_FIRSTBURSTLENGTH;
  841: 	}
  842: 	istgt->FirstBurstLength = FirstBurstLength;
  843: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "FirstBurstLength %d\n",
  844: 	    istgt->FirstBurstLength);
  845: 
  846: 	MaxBurstLength = istgt_get_intval(sp, "MaxBurstLength");
  847: 	if (MaxBurstLength < 0) {
  848: 		MaxBurstLength = DEFAULT_MAXBURSTLENGTH;
  849: 	}
  850: 	istgt->MaxBurstLength = MaxBurstLength;
  851: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxBurstLength %d\n",
  852: 	    istgt->MaxBurstLength);
  853: 
  854: 	MaxRecvDataSegmentLength
  855: 		= istgt_get_intval(sp, "MaxRecvDataSegmentLength");
  856: 	if (MaxRecvDataSegmentLength < 0) {
  857: 		MaxRecvDataSegmentLength = DEFAULT_MAXRECVDATASEGMENTLENGTH;
  858: 	}
  859: 	istgt->MaxRecvDataSegmentLength = MaxRecvDataSegmentLength;
  860: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxRecvDataSegmentLength %d\n",
  861: 	    istgt->MaxRecvDataSegmentLength);
  862: 
  863: 	/* check size limit (up to 24bits - RFC3720(12.12)) */
  864: 	if (istgt->MaxBurstLength < 512) {
  865: 		ISTGT_ERRLOG("MaxBurstLength(%d) < 512\n",
  866: 		    istgt->MaxBurstLength);
  867: 		return -1;
  868: 	}
  869: 	if (istgt->FirstBurstLength < 512) {
  870: 		ISTGT_ERRLOG("FirstBurstLength(%d) < 512\n",
  871: 		    istgt->FirstBurstLength);
  872: 		return -1;
  873: 	}
  874: 	if (istgt->FirstBurstLength > istgt->MaxBurstLength) {
  875: 		ISTGT_ERRLOG("FirstBurstLength(%d) > MaxBurstLength(%d)\n",
  876: 		    istgt->FirstBurstLength, istgt->MaxBurstLength);
  877: 		return -1;
  878: 	}
  879: 	if (istgt->MaxBurstLength > 0x00ffffff) {
  880: 		ISTGT_ERRLOG("MaxBurstLength(%d) > 0x00ffffff\n",
  881: 		    istgt->MaxBurstLength);
  882: 		return -1;
  883: 	}
  884: 	if (istgt->MaxRecvDataSegmentLength < 512) {
  885: 		ISTGT_ERRLOG("MaxRecvDataSegmentLength(%d) < 512\n",
  886: 		    istgt->MaxRecvDataSegmentLength);
  887: 		return -1;
  888: 	}
  889: 	if (istgt->MaxRecvDataSegmentLength > 0x00ffffff) {
  890: 		ISTGT_ERRLOG("MaxRecvDataSegmentLength(%d) > 0x00ffffff\n",
  891: 		    istgt->MaxRecvDataSegmentLength);
  892: 		return -1;
  893: 	}
  894: 
  895: 	val = istgt_get_val(sp, "InitialR2T");
  896: 	if (val == NULL) {
  897: 		InitialR2T = DEFAULT_INITIALR2T;
  898: 	} else if (strcasecmp(val, "Yes") == 0) {
  899: 		InitialR2T = 1;
  900: 	} else if (strcasecmp(val, "No") == 0) {
  901: #if 0
  902: 		InitialR2T = 0;
  903: #else
  904: 		ISTGT_ERRLOG("not supported value %s\n", val);
  905: 		return -1;
  906: #endif
  907: 	} else {
  908: 		ISTGT_ERRLOG("unknown value %s\n", val);
  909: 		return -1;
  910: 	}
  911: 	istgt->InitialR2T = InitialR2T;
  912: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "InitialR2T %s\n",
  913: 	    istgt->InitialR2T ? "Yes" : "No");
  914: 
  915: 	val = istgt_get_val(sp, "ImmediateData");
  916: 	if (val == NULL) {
  917: 		ImmediateData = DEFAULT_IMMEDIATEDATA;
  918: 	} else if (strcasecmp(val, "Yes") == 0) {
  919: 		ImmediateData = 1;
  920: 	} else if (strcasecmp(val, "No") == 0) {
  921: 		ImmediateData = 0;
  922: 	} else {
  923: 		ISTGT_ERRLOG("unknown value %s\n", val);
  924: 		return -1;
  925: 	}
  926: 	istgt->ImmediateData = ImmediateData;
  927: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "ImmediateData %s\n",
  928: 	    istgt->ImmediateData ? "Yes" : "No");
  929: 
  930: 	val = istgt_get_val(sp, "DataPDUInOrder");
  931: 	if (val == NULL) {
  932: 		DataPDUInOrder = DEFAULT_DATAPDUINORDER;
  933: 	} else if (strcasecmp(val, "Yes") == 0) {
  934: 		DataPDUInOrder = 1;
  935: 	} else if (strcasecmp(val, "No") == 0) {
  936: #if 0
  937: 		DataPDUInOrder = 0;
  938: #else
  939: 		ISTGT_ERRLOG("not supported value %s\n", val);
  940: 		return -1;
  941: #endif
  942: 	} else {
  943: 		ISTGT_ERRLOG("unknown value %s\n", val);
  944: 		return -1;
  945: 	}
  946: 	istgt->DataPDUInOrder = DataPDUInOrder;
  947: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DataPDUInOrder %s\n",
  948: 	    istgt->DataPDUInOrder ? "Yes" : "No");
  949: 
  950: 	val = istgt_get_val(sp, "DataSequenceInOrder");
  951: 	if (val == NULL) {
  952: 		DataSequenceInOrder = DEFAULT_DATASEQUENCEINORDER;
  953: 	} else if (strcasecmp(val, "Yes") == 0) {
  954: 		DataSequenceInOrder = 1;
  955: 	} else if (strcasecmp(val, "No") == 0) {
  956: #if 0
  957: 		DataSequenceInOrder = 0;
  958: #else
  959: 		ISTGT_ERRLOG("not supported value %s\n", val);
  960: 		return -1;
  961: #endif
  962: 	} else {
  963: 		ISTGT_ERRLOG("unknown value %s\n", val);
  964: 		return -1;
  965: 	}
  966: 	istgt->DataSequenceInOrder = DataSequenceInOrder;
  967: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DataSequenceInOrder %s\n",
  968: 	    istgt->DataSequenceInOrder ? "Yes" : "No");
  969: 
  970: 	ErrorRecoveryLevel = istgt_get_intval(sp, "ErrorRecoveryLevel");
  971: 	if (ErrorRecoveryLevel < 0) {
  972: 		ErrorRecoveryLevel = DEFAULT_ERRORRECOVERYLEVEL;
  973: 	} else if (ErrorRecoveryLevel == 0) {
  974: 		ErrorRecoveryLevel = 0;
  975: 	} else if (ErrorRecoveryLevel == 1) {
  976: #if 0
  977: 		ErrorRecoveryLevel = 1;
  978: #else
  979: 		ISTGT_ERRLOG("not supported value %d\n", ErrorRecoveryLevel);
  980: 		return -1;
  981: #endif
  982: 	} else if (ErrorRecoveryLevel == 2) {
  983: #if 0
  984: 		ErrorRecoveryLevel = 2;
  985: #else
  986: 		ISTGT_ERRLOG("not supported value %d\n", ErrorRecoveryLevel);
  987: 		return -1;
  988: #endif
  989: 	} else {
  990: 		ISTGT_ERRLOG("not supported value %d\n", ErrorRecoveryLevel);
  991: 		return -1;
  992: 	}
  993: 	istgt->ErrorRecoveryLevel = ErrorRecoveryLevel;
  994: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "ErrorRecoveryLevel %d\n",
  995: 	    istgt->ErrorRecoveryLevel);
  996: 
  997: 	timeout = istgt_get_intval(sp, "Timeout");
  998: 	if (timeout < 0) {
  999: 		timeout = DEFAULT_TIMEOUT;
 1000: 	}
 1001: 	istgt->timeout = timeout;
 1002: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Timeout %d\n",
 1003: 	    istgt->timeout);
 1004: 
 1005: 	nopininterval = istgt_get_intval(sp, "NopInInterval");
 1006: 	if (nopininterval < 0) {
 1007: 		nopininterval = DEFAULT_NOPININTERVAL;
 1008: 	}
 1009: 	istgt->nopininterval = nopininterval;
 1010: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "NopInInterval %d\n",
 1011: 	    istgt->nopininterval);
 1012: 
 1013: 	maxr2t = istgt_get_intval(sp, "MaxR2T");
 1014: 	if (maxr2t < 0) {
 1015: 		maxr2t = DEFAULT_MAXR2T;
 1016: 	}
 1017: 	if (maxr2t > MAX_R2T) {
 1018: 		ISTGT_ERRLOG("MaxR2T(%d) > %d\n",
 1019: 		    maxr2t, MAX_R2T);
 1020: 		return -1;
 1021: 	}
 1022: 	istgt->maxr2t = maxr2t;
 1023: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxR2T %d\n",
 1024: 	    istgt->maxr2t);
 1025: 
 1026: 	val = istgt_get_val(sp, "DiscoveryAuthMethod");
 1027: 	if (val == NULL) {
 1028: 		istgt->no_discovery_auth = 0;
 1029: 		istgt->req_discovery_auth = 0;
 1030: 		istgt->req_discovery_auth_mutual = 0;
 1031: 	} else {
 1032: 		istgt->no_discovery_auth = 0;
 1033: 		for (i = 0; ; i++) {
 1034: 			val = istgt_get_nmval(sp, "DiscoveryAuthMethod", 0, i);
 1035: 			if (val == NULL)
 1036: 				break;
 1037: 			if (strcasecmp(val, "CHAP") == 0) {
 1038: 				istgt->req_discovery_auth = 1;
 1039: 			} else if (strcasecmp(val, "Mutual") == 0) {
 1040: 				istgt->req_discovery_auth_mutual = 1;
 1041: 			} else if (strcasecmp(val, "Auto") == 0) {
 1042: 				istgt->req_discovery_auth = 0;
 1043: 				istgt->req_discovery_auth_mutual = 0;
 1044: 			} else if (strcasecmp(val, "None") == 0) {
 1045: 				istgt->no_discovery_auth = 1;
 1046: 				istgt->req_discovery_auth = 0;
 1047: 				istgt->req_discovery_auth_mutual = 0;
 1048: 			} else {
 1049: 				ISTGT_ERRLOG("unknown auth\n");
 1050: 				return -1;
 1051: 			}
 1052: 		}
 1053: 		if (istgt->req_discovery_auth_mutual && !istgt->req_discovery_auth) {
 1054: 			ISTGT_ERRLOG("Mutual but not CHAP\n");
 1055: 			return -1;
 1056: 		}
 1057: 	}
 1058: 	if (istgt->no_discovery_auth != 0) {
 1059: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 1060: 		    "DiscoveryAuthMethod None\n");
 1061: 	} else if (istgt->req_discovery_auth == 0) {
 1062: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 1063: 		    "DiscoveryAuthMethod Auto\n");
 1064: 	} else {
 1065: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 1066: 		    "DiscoveryAuthMethod %s %s\n",
 1067: 		    istgt->req_discovery_auth ? "CHAP" : "",
 1068: 		    istgt->req_discovery_auth_mutual ? "Mutual" : "");
 1069: 	}
 1070: 
 1071: 	val = istgt_get_val(sp, "DiscoveryAuthGroup");
 1072: 	if (val == NULL) {
 1073: 		istgt->discovery_auth_group = 0;
 1074: 	} else {
 1075: 		ag_tag = val;
 1076: 		if (strcasecmp(ag_tag, "None") == 0) {
 1077: 			ag_tag_i = 0;
 1078: 		} else {
 1079: 			if (strncasecmp(ag_tag, "AuthGroup",
 1080: 				strlen("AuthGroup")) != 0
 1081: 			    || sscanf(ag_tag, "%*[^0-9]%d", &ag_tag_i) != 1) {
 1082: 				ISTGT_ERRLOG("auth group error\n");
 1083: 				return -1;
 1084: 			}
 1085: 			if (ag_tag_i == 0) {
 1086: 				ISTGT_ERRLOG("invalid auth group %d\n",
 1087: 				    ag_tag_i);
 1088: 				return -1;
 1089: 			}
 1090: 		}
 1091: 		istgt->discovery_auth_group = ag_tag_i;
 1092: 	}
 1093: 	if (istgt->discovery_auth_group == 0) {
 1094: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 1095: 		    "DiscoveryAuthGroup None\n");
 1096: 	} else {
 1097: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 1098: 		    "DiscoveryAuthGroup AuthGroup%d\n",
 1099: 		    istgt->discovery_auth_group);
 1100: 	}
 1101: 
 1102: 	rc = istgt_init_uctl(istgt);
 1103: 	if (rc < 0) {
 1104: 		ISTGT_ERRLOG("istgt_init_uctl() failed\n");
 1105: 		return -1;
 1106: 	}
 1107: 	rc = istgt_build_uctl_portal(istgt);
 1108: 	if (rc < 0) {
 1109: 		ISTGT_ERRLOG("istgt_build_uctl_portal() failed\n");
 1110: 		return -1;
 1111: 	}
 1112: 	rc = istgt_build_portal_array(istgt);
 1113: 	if (rc < 0) {
 1114: 		ISTGT_ERRLOG("istgt_build_portal_array() failed\n");
 1115: 		return -1;
 1116: 	}
 1117: 	rc = istgt_build_initiator_group_array(istgt);
 1118: 	if (rc < 0) {
 1119: 		ISTGT_ERRLOG("build_initiator_group_array() failed\n");
 1120: 		return -1;
 1121: 	}
 1122: 
 1123: 	rc = pthread_attr_init(&istgt->attr);
 1124: 	if (rc != 0) {
 1125: 		ISTGT_ERRLOG("pthread_attr_init() failed\n");
 1126: 		return -1;
 1127: 	}
 1128: 	rc = pthread_attr_getstacksize(&istgt->attr, &stacksize);
 1129: 	if (rc != 0) {
 1130: 		ISTGT_ERRLOG("pthread_attr_getstacksize() failed\n");
 1131: 		return -1;
 1132: 	}
 1133: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "current thread stack = %zd\n", stacksize);
 1134: 	if (stacksize < ISTGT_STACKSIZE) {
 1135: 		stacksize = ISTGT_STACKSIZE;
 1136: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "new thread stack = %zd\n", stacksize);
 1137: 		rc = pthread_attr_setstacksize(&istgt->attr, stacksize);
 1138: 		if (rc != 0) {
 1139: 			ISTGT_ERRLOG("pthread_attr_setstacksize() failed\n");
 1140: 			return -1;
 1141: 		}
 1142: 	}
 1143: 
 1144: 	rc = pthread_mutex_init(&istgt->mutex, NULL);
 1145: 	if (rc != 0) {
 1146: 		ISTGT_ERRLOG("mutex_init() failed\n");
 1147: 		return -1;
 1148: 	}
 1149: 
 1150: 	/* XXX TODO: add initializer */
 1151: 
 1152: 	istgt_set_state(istgt, ISTGT_STATE_INITIALIZED);
 1153: 
 1154: 	return 0;
 1155: }
 1156: 
 1157: #ifdef SIGINFO
 1158: static void
 1159: istgt_siginfo(int signo)
 1160: {
 1161: 	/* nothing */
 1162: }
 1163: #endif
 1164: 
 1165: static void
 1166: istgt_sigwakeup(int signo)
 1167: {
 1168: }
 1169: 
 1170: #ifdef SIGIO
 1171: static void
 1172: istgt_sigio(int signo)
 1173: {
 1174: }
 1175: #endif
 1176: 
 1177: static void *
 1178: istgt_sighandler(void *arg)
 1179: {
 1180: 	ISTGT_Ptr istgt = (ISTGT_Ptr) arg;
 1181: 	sigset_t signew;
 1182: 	int signo;
 1183: 
 1184: 	sigemptyset(&signew);
 1185: 	sigaddset(&signew, SIGINT);
 1186: 	sigaddset(&signew, SIGTERM);
 1187: 	sigaddset(&signew, SIGQUIT);
 1188: 	sigaddset(&signew, SIGHUP);
 1189: #ifdef SIGINFO
 1190: 	sigaddset(&signew, SIGINFO);
 1191: #endif
 1192: 	sigaddset(&signew, SIGUSR1);
 1193: 	sigaddset(&signew, SIGUSR2);
 1194: #ifdef SIGIO
 1195: 	sigaddset(&signew, SIGIO);
 1196: #endif
 1197: 
 1198: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop start\n");
 1199: 	while (1) {
 1200: 		if (istgt_get_state(istgt) == ISTGT_STATE_EXITING
 1201: 		    || istgt_get_state(istgt) == ISTGT_STATE_SHUTDOWN) {
 1202: 			break;
 1203: 		}
 1204: 		sigwait(&signew, &signo);
 1205: 		switch (signo) {
 1206: 		case SIGINT:
 1207: 			printf("SIGINT catch\n");
 1208: 			istgt_set_state(istgt, ISTGT_STATE_EXITING);
 1209: 			istgt_lu_set_all_state(istgt, ISTGT_STATE_EXITING);
 1210: 			break;
 1211: 		case SIGTERM:
 1212: 			printf("SIGTERM catch\n");
 1213: 			istgt_set_state(istgt, ISTGT_STATE_EXITING);
 1214: 			istgt_lu_set_all_state(istgt, ISTGT_STATE_EXITING);
 1215: 			break;
 1216: 		case SIGQUIT:
 1217: 			printf("SIGQUIT catch\n");
 1218: 			exit(EXIT_SUCCESS);
 1219: 			break;
 1220: 		case SIGHUP:
 1221: 			printf("SIGHUP catch\n");
 1222: 			break;
 1223: #ifdef SIGINFO
 1224: 		case SIGINFO:
 1225: 			printf("SIGINFO catch\n");
 1226: 			istgt_set_trace_flag(ISTGT_TRACE_ISCSI);
 1227: 			break;
 1228: #endif
 1229: 		case SIGUSR1:
 1230: 			printf("SIGUSR1 catch\n");
 1231: 			istgt_set_trace_flag(ISTGT_TRACE_NONE);
 1232: 			break;
 1233: 		case SIGUSR2:
 1234: 			printf("SIGUSR2 catch\n");
 1235: 			//istgt_set_trace_flag(ISTGT_TRACE_SCSI);
 1236: 			istgt_set_trace_flag(ISTGT_TRACE_ALL);
 1237: 			break;
 1238: #ifdef SIGIO
 1239: 		case SIGIO:
 1240: 			//printf("SIGIO catch\n");
 1241: 			break;
 1242: #endif
 1243: 		default:
 1244: 			break;
 1245: 		}
 1246: 	}
 1247: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop ended\n");
 1248: 
 1249: 	return NULL;
 1250: }
 1251: 
 1252: static int
 1253: istgt_acceptor(ISTGT_Ptr istgt)
 1254: {
 1255: #ifdef ISTGT_USE_KQUEUE
 1256: 	int kq;
 1257: 	struct kevent kev;
 1258: 	struct timespec kev_timeout;
 1259: #else
 1260: 	struct pollfd fds[MAX_PORTAL + MAX_UCPORTAL];
 1261: #endif /* ISTGT_USE_KQUEUE */
 1262: 	struct sockaddr_storage sa;
 1263: 	socklen_t salen;
 1264: 	int sock;
 1265: 	int rc, n;
 1266: 	int ucidx;
 1267: 	int nidx;
 1268: 	int i;
 1269: 
 1270: 	if (istgt_get_state(istgt) != ISTGT_STATE_INITIALIZED) {
 1271: 		ISTGT_ERRLOG("not initialized\n");
 1272: 		return -1;
 1273: 	}
 1274: 	/* now running main thread */
 1275: 	istgt_set_state(istgt, ISTGT_STATE_RUNNING);
 1276: 
 1277: #ifdef ISTGT_USE_KQUEUE
 1278: 	kq = kqueue();
 1279: 	if (kq == -1) {
 1280: 		ISTGT_ERRLOG("kqueue() failed\n");
 1281: 		return -1;
 1282: 	}
 1283: 	for (i = 0; i < istgt->nportal; i++) {
 1284: 		EV_SET(&kev, istgt->portal[i].sock,
 1285: 		    EVFILT_READ, EV_ADD, 0, 0, NULL);
 1286: 		rc = kevent(kq, &kev, 1, NULL, 0, NULL);
 1287: 		if (rc == -1) {
 1288: 			ISTGT_ERRLOG("kevent() failed\n");
 1289: 			close(kq);
 1290: 			return -1;
 1291: 		}
 1292: 	}
 1293: 	ucidx = istgt->nportal;
 1294: 	for (i = 0; i < istgt->nuctl_portal; i++) {
 1295: 		EV_SET(&kev, istgt->uctl_portal[i].sock,
 1296: 		    EVFILT_READ, EV_ADD, 0, 0, NULL);
 1297: 		rc = kevent(kq, &kev, 1, NULL, 0, NULL);
 1298: 		if (rc == -1) {
 1299: 			ISTGT_ERRLOG("kevent() failed\n");
 1300: 			close(kq);
 1301: 			return -1;
 1302: 		}
 1303: 	}
 1304: 	nidx = istgt->nportal + istgt->nuctl_portal;
 1305: 
 1306: 	EV_SET(&kev, SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
 1307: 	rc = kevent(kq, &kev, 1, NULL, 0, NULL);
 1308: 	if (rc == -1) {
 1309: 		ISTGT_ERRLOG("kevent() failed\n");
 1310: 		close(kq);
 1311: 		return -1;
 1312: 	}
 1313: 	EV_SET(&kev, SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
 1314: 	rc = kevent(kq, &kev, 1, NULL, 0, NULL);
 1315: 	if (rc == -1) {
 1316: 		ISTGT_ERRLOG("kevent() failed\n");
 1317: 		close(kq);
 1318: 		return -1;
 1319: 	}
 1320: #else
 1321: 	memset(&fds, 0, sizeof fds);
 1322: 	for (i = 0; i < istgt->nportal; i++) {
 1323: 		fds[i].fd = istgt->portal[i].sock;
 1324: 		fds[i].events = POLLIN;
 1325: 	}
 1326: 	ucidx = istgt->nportal;
 1327: 	for (i = 0; i < istgt->nuctl_portal; i++) {
 1328: 		fds[ucidx + i].fd = istgt->uctl_portal[i].sock;
 1329: 		fds[ucidx + i].events = POLLIN;
 1330: 	}
 1331: 	nidx = istgt->nportal + istgt->nuctl_portal;
 1332: #endif /* ISTGT_USE_KQUEUE */
 1333: 
 1334: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop start\n");
 1335: 	while (1) {
 1336: 		if (istgt_get_state(istgt) != ISTGT_STATE_RUNNING) {
 1337: 			break;
 1338: 		}
 1339: #ifdef ISTGT_USE_KQUEUE
 1340: 		//ISTGT_TRACELOG(ISTGT_TRACE_NET, "kevent %d\n", nidx);
 1341: 		kev_timeout.tv_sec = 10;
 1342: 		kev_timeout.tv_nsec = 0;
 1343: 		rc = kevent(kq, NULL, 0, &kev, 1, &kev_timeout);
 1344: 		if (rc == -1 && errno == EINTR) {
 1345: 			continue;
 1346: 		}
 1347: 		if (rc == -1) {
 1348: 			ISTGT_ERRLOG("kevent() failed\n");
 1349: 			break;
 1350: 		}
 1351: 		if (rc == 0) {
 1352: 			/* idle timeout */
 1353: 			continue;
 1354: 		}
 1355: 		if (kev.filter == EVFILT_SIGNAL) {
 1356: 			ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "kevent SIGNAL\n");
 1357: 			if (kev.ident == SIGINT || kev.ident == SIGTERM) {
 1358: 				ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 1359: 				    "kevent SIGNAL SIGINT/SIGTERM\n");
 1360: 				break;
 1361: 			}
 1362: 			continue;
 1363: 		}
 1364: #else
 1365: 		//ISTGT_TRACELOG(ISTGT_TRACE_NET, "poll %d\n", nidx);
 1366: 		rc = poll(fds, nidx, POLLWAIT);
 1367: 		if (rc == -1 && errno == EINTR) {
 1368: 			continue;
 1369: 		}
 1370: 		if (rc == -1) {
 1371: 			ISTGT_ERRLOG("poll() failed\n");
 1372: 			break;
 1373: 		}
 1374: 		if (rc == 0) {
 1375: 			/* no fds */
 1376: 			continue;
 1377: 		}
 1378: #endif /* ISTGT_USE_KQUEUE */
 1379: 
 1380: 		n = rc;
 1381: 		for (i = 0; n != 0 && i < istgt->nportal; i++) {
 1382: #ifdef ISTGT_USE_KQUEUE
 1383: 			if (kev.ident == istgt->portal[i].sock) {
 1384: 				if (kev.flags) {
 1385: 					ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 1386: 					    "flags %x\n",
 1387: 					    kev.flags);
 1388: 				}
 1389: #else
 1390: 			if (fds[i].revents) {
 1391: 				ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 1392: 				    "events %x\n",
 1393: 				    fds[i].revents);
 1394: 			}
 1395: 			if (fds[i].revents & POLLIN) {
 1396: #endif /* ISTGT_USE_KQUEUE */
 1397: 				n--;
 1398: 				memset(&sa, 0, sizeof(sa));
 1399: 				salen = sizeof(sa);
 1400: #ifdef ISTGT_USE_KQUEUE
 1401: 				ISTGT_TRACELOG(ISTGT_TRACE_NET, "accept %d\n",
 1402: 				    kev.ident);
 1403: 				rc = accept(kev.ident, (struct sockaddr *) &sa, &salen);
 1404: #else
 1405: 				ISTGT_TRACELOG(ISTGT_TRACE_NET, "accept %d\n",
 1406: 				    fds[i].fd);
 1407: 				rc = accept(fds[i].fd, (struct sockaddr *) &sa, &salen);
 1408: #endif /* ISTGT_USE_KQUEUE */
 1409: 				if (rc < 0) {
 1410: 					ISTGT_ERRLOG("accept error: %d\n", rc);
 1411: 					continue;
 1412: 				}
 1413: 				sock = rc;
 1414: #if 0
 1415: 				rc = fcntl(sock, F_GETFL, 0);
 1416: 				if (rc == -1) {
 1417: 					ISTGT_ERRLOG("fcntl() failed\n");
 1418: 					continue;
 1419: 				}
 1420: 				rc = fcntl(sock, F_SETFL, (rc | O_NONBLOCK));
 1421: 				if (rc == -1) {
 1422: 					ISTGT_ERRLOG("fcntl() failed\n");
 1423: 					continue;
 1424: 				}
 1425: #endif
 1426: 				rc = istgt_create_conn(istgt,
 1427: 				    &istgt->portal[i], sock,
 1428: 				    (struct sockaddr *) &sa, salen);
 1429: 				if (rc < 0) {
 1430: 					close(sock);
 1431: 					ISTGT_ERRLOG("istgt_create_conn() failed\n");
 1432: 					continue;
 1433: 				}
 1434: 			}
 1435: 		}
 1436: 
 1437: 		/* check for control */
 1438: 		for (i = 0; n != 0 && i < istgt->nuctl_portal; i++) {
 1439: #ifdef ISTGT_USE_KQUEUE
 1440: 			if (kev.ident == istgt->uctl_portal[i].sock) {
 1441: 				if (kev.flags) {
 1442: 					ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 1443: 					    "flags %x\n",
 1444: 					    kev.flags);
 1445: 				}
 1446: #else
 1447: 			if (fds[ucidx + i].revents) {
 1448: 				ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 1449: 				    "events %x\n",
 1450: 				    fds[ucidx + i].revents);
 1451: 			}
 1452: 			if (fds[ucidx + i].revents & POLLIN) {
 1453: #endif /* ISTGT_USE_KQUEUE */
 1454: 				n--;
 1455: 				memset(&sa, 0, sizeof(sa));
 1456: 				salen = sizeof(sa);
 1457: #ifdef ISTGT_USE_KQUEUE
 1458: 				ISTGT_TRACELOG(ISTGT_TRACE_NET,
 1459: 				    "accept %d\n", kev.ident);
 1460: 				rc = accept(kev.ident,
 1461: 				    (struct sockaddr *) &sa, &salen);
 1462: #else
 1463: 				ISTGT_TRACELOG(ISTGT_TRACE_NET,
 1464: 				    "accept %d\n", fds[ucidx + i].fd);
 1465: 				rc = accept(fds[ucidx + i].fd,
 1466: 				    (struct sockaddr *) &sa, &salen);
 1467: #endif /* ISTGT_USE_KQUEUE */
 1468: 				if (rc < 0) {
 1469: 					ISTGT_ERRLOG("accept error: %d\n", rc);
 1470: 					continue;
 1471: 				}
 1472: 				sock = rc;
 1473: 				rc = istgt_create_uctl(istgt,
 1474: 				    &istgt->uctl_portal[i], sock,
 1475: 				    (struct sockaddr *) &sa, salen);
 1476: 				if (rc < 0) {
 1477: 					close(sock);
 1478: 					ISTGT_ERRLOG("istgt_create_uctl() failed\n");
 1479: 					continue;
 1480: 				}
 1481: 			}
 1482: 		}
 1483: 	}
 1484: #ifdef ISTGT_USE_KQUEUE
 1485: 	close(kq);
 1486: #endif /* ISTGT_USE_KQUEUE */
 1487: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop ended\n");
 1488: 	istgt_set_state(istgt, ISTGT_STATE_EXITING);
 1489: 
 1490: 	return 0;
 1491: }
 1492: 
 1493: static void
 1494: usage(void)
 1495: {
 1496: 	printf("istgt [options]\n");
 1497: 	printf("options:\n");
 1498: 	printf(" -c config  config file (default %s)\n", DEFAULT_CONFIG);
 1499: 	printf(" -p pidfile use specific file\n");
 1500: 	printf(" -l facility use specific syslog facility (default %s)\n",
 1501: 	    DEFAULT_LOG_FACILITY);
 1502: 	printf(" -m mode    operational mode (default %d, 0=traditional, "
 1503: 	    "1=normal, 2=experimental)\n", DEFAULT_ISTGT_SWMODE);
 1504: 	printf(" -t flag    trace flag (all, net, iscsi, scsi, lu)\n");
 1505: 	printf(" -q         quiet warnings\n");
 1506: 	printf(" -D         don't detach from tty\n");
 1507: 	printf(" -H         show this usage\n");
 1508: 	printf(" -V         show version\n");
 1509: }
 1510: 
 1511: int
 1512: main(int argc, char **argv)
 1513: {
 1514: 	ISTGT_Ptr istgt;
 1515: 	const char *config_file = DEFAULT_CONFIG;
 1516: 	const char *pidfile = NULL;
 1517: 	const char *logfacility = NULL;
 1518: 	const char *logpriority = NULL;
 1519: 	CONFIG *config;
 1520: 	pthread_t sigthread;
 1521: 	struct sigaction sigact, sigoldact_pipe, sigoldact_info;
 1522: 	struct sigaction sigoldact_wakeup, sigoldact_io;
 1523: 	sigset_t signew, sigold;
 1524: 	int retry = 10;
 1525: 	int detach = 1;
 1526: 	int swmode;
 1527: 	int ch;
 1528: 	int rc;
 1529: 
 1530: 	if (sizeof (ISCSI_BHS) != ISCSI_BHS_LEN) {
 1531: 		fprintf(stderr, "Internal Error\n");
 1532: 		exit(EXIT_FAILURE);
 1533: 	}
 1534: 
 1535: 	memset(&g_istgt, 0, sizeof g_istgt);
 1536: 	istgt = &g_istgt;
 1537: 	istgt_set_state(istgt, ISTGT_STATE_INVALID);
 1538: 	istgt->swmode = DEFAULT_ISTGT_SWMODE;
 1539: 
 1540: 	while ((ch = getopt(argc, argv, "c:p:l:m:t:qDHV")) != -1) {
 1541: 		switch (ch) {
 1542: 		case 'c':
 1543: 			config_file = optarg;
 1544: 			break;
 1545: 		case 'p':
 1546: 			pidfile = optarg;
 1547: 			break;
 1548: 		case 'l':
 1549: 			logfacility = optarg;
 1550: 			break;
 1551: 		case 'm':
 1552: 			swmode = strtol(optarg, NULL, 10);
 1553: 			if (swmode == ISTGT_SWMODE_TRADITIONAL
 1554: 			    || swmode == ISTGT_SWMODE_NORMAL
 1555: 			    || swmode == ISTGT_SWMODE_EXPERIMENTAL) {
 1556: 				istgt->swmode = swmode;
 1557: 			} else {
 1558: 				fprintf(stderr, "unknown mode %x\n", swmode);
 1559: 				usage();
 1560: 				exit(EXIT_FAILURE);
 1561: 			}
 1562: 			break;
 1563: 		case 't':
 1564: 			if (strcasecmp(optarg, "NET") == 0) {
 1565: 				istgt_set_trace_flag(ISTGT_TRACE_NET);
 1566: 			} else if (strcasecmp(optarg, "ISCSI") == 0) {
 1567: 				istgt_set_trace_flag(ISTGT_TRACE_ISCSI);
 1568: 			} else if (strcasecmp(optarg, "SCSI") == 0) {
 1569: 				istgt_set_trace_flag(ISTGT_TRACE_SCSI);
 1570: 			} else if (strcasecmp(optarg, "LU") == 0) {
 1571: 				istgt_set_trace_flag(ISTGT_TRACE_LU);
 1572: 			} else if (strcasecmp(optarg, "ALL") == 0) {
 1573: 				istgt_set_trace_flag(ISTGT_TRACE_ALL);
 1574: 			} else if (strcasecmp(optarg, "NONE") == 0) {
 1575: 				istgt_set_trace_flag(ISTGT_TRACE_NONE);
 1576: 			} else {
 1577: 				fprintf(stderr, "unknown flag\n");
 1578: 				usage();
 1579: 				exit(EXIT_FAILURE);
 1580: 			}
 1581: 			break;
 1582: 		case 'q':
 1583: 			g_warn_flag = 0;
 1584: 			break;
 1585: 		case 'D':
 1586: 			detach = 0;
 1587: 			break;
 1588: 		case 'V':
 1589: 			printf("istgt version %s\n", ISTGT_VERSION);
 1590: 			printf("istgt extra version %s\n", ISTGT_EXTRA_VERSION);
 1591: 			exit(EXIT_SUCCESS);
 1592: 		case 'H':
 1593: 		default:
 1594: 			usage();
 1595: 			exit(EXIT_SUCCESS);
 1596: 		}
 1597: 	}
 1598: 
 1599: 	/* read config files */
 1600: 	config = istgt_allocate_config();
 1601: 	rc = istgt_read_config(config, config_file);
 1602: 	if (rc < 0) {
 1603: 		fprintf(stderr, "config error\n");
 1604: 		exit(EXIT_FAILURE);
 1605: 	}
 1606: 	if (config->section == NULL) {
 1607: 		fprintf(stderr, "empty config\n");
 1608: 		istgt_free_config(config);
 1609: 		exit(EXIT_FAILURE);
 1610: 	}
 1611: 	istgt->config = config;
 1612: 	//istgt_print_config(config);
 1613: 
 1614: 	/* open log files */
 1615: 	if (logfacility == NULL) {
 1616: 		logfacility = istgt_get_log_facility(config);
 1617: 	}
 1618: 	rc = istgt_set_log_facility(logfacility);
 1619: 	if (rc < 0) {
 1620: 		fprintf(stderr, "log facility error\n");
 1621: 		istgt_free_config(config);
 1622: 		exit(EXIT_FAILURE);
 1623: 	}
 1624: 	if (logpriority == NULL) {
 1625: 		logpriority = DEFAULT_LOG_PRIORITY;
 1626: 	}
 1627: 	rc = istgt_set_log_priority(logpriority);
 1628: 	if (rc < 0) {
 1629: 		fprintf(stderr, "log priority error\n");
 1630: 		istgt_free_config(config);
 1631: 		exit(EXIT_FAILURE);
 1632: 	}
 1633: 	istgt_open_log();
 1634: 
 1635: 	ISTGT_NOTICELOG("istgt version %s (%s)\n", ISTGT_VERSION,
 1636: 	    ISTGT_EXTRA_VERSION);
 1637: 	switch (istgt->swmode) {
 1638: 	case ISTGT_SWMODE_TRADITIONAL:
 1639: 		ISTGT_NOTICELOG("traditional mode\n");
 1640: 		break;
 1641: 	case ISTGT_SWMODE_NORMAL:
 1642: 		ISTGT_NOTICELOG("normal mode\n");
 1643: 		break;
 1644: 	case ISTGT_SWMODE_EXPERIMENTAL:
 1645: 		ISTGT_NOTICELOG("experimental mode\n");
 1646: 		break;
 1647: 	default:
 1648: 		break;
 1649: 	}
 1650: 
 1651: #ifdef ISTGT_USE_CRC32C_TABLE
 1652: 	/* build crc32c table */
 1653: 	istgt_init_crc32c_table();
 1654: #endif /* ISTGT_USE_CRC32C_TABLE */
 1655: 
 1656: 	/* initialize sub modules */
 1657: 	rc = istgt_init(istgt);
 1658: 	if (rc < 0) {
 1659: 		ISTGT_ERRLOG("istgt_init() failed\n");
 1660: 	initialize_error:
 1661: 		istgt_close_log();
 1662: 		istgt_free_config(config);
 1663: 		exit(EXIT_FAILURE);
 1664: 	}
 1665: 	rc = istgt_lu_init(istgt);
 1666: 	if (rc < 0) {
 1667: 		ISTGT_ERRLOG("istgt_lu_init() failed\n");
 1668: 		goto initialize_error;
 1669: 	}
 1670: 	rc = istgt_iscsi_init(istgt);
 1671: 	if (rc < 0) {
 1672: 		ISTGT_ERRLOG("istgt_iscsi_init() failed\n");
 1673: 		goto initialize_error;
 1674: 	}
 1675: 
 1676: 	/* override by command line */
 1677: 	if (pidfile != NULL) {
 1678: 		xfree(istgt->pidfile);
 1679: 		istgt->pidfile = xstrdup(pidfile);
 1680: 	}
 1681: 
 1682: 	/* detach from tty and run background */
 1683: 	fflush(stdout);
 1684: 	if (detach) {
 1685: 		rc = daemon(0, 0);
 1686: 		if (rc < 0) {
 1687: 			ISTGT_ERRLOG("daemon() failed\n");
 1688: 			goto initialize_error;
 1689: 		}
 1690: 	}
 1691: 
 1692: 	/* setup signal handler thread */
 1693: 	memset(&sigact, 0, sizeof sigact);
 1694: 	memset(&sigoldact_pipe, 0, sizeof sigoldact_pipe);
 1695: 	memset(&sigoldact_info, 0, sizeof sigoldact_info);
 1696: 	memset(&sigoldact_wakeup, 0, sizeof sigoldact_wakeup);
 1697: 	memset(&sigoldact_io, 0, sizeof sigoldact_io);
 1698: 	sigact.sa_handler = SIG_IGN;
 1699: 	sigemptyset(&sigact.sa_mask);
 1700: 	rc = sigaction(SIGPIPE, &sigact, &sigoldact_pipe);
 1701: 	if (rc < 0) {
 1702: 		ISTGT_ERRLOG("sigaction(SIGPIPE) failed\n");
 1703: 		goto initialize_error;
 1704: 	}
 1705: #ifdef SIGINFO
 1706: 	sigact.sa_handler = istgt_siginfo;
 1707: 	sigemptyset(&sigact.sa_mask);
 1708: 	rc = sigaction(SIGINFO, &sigact, &sigoldact_info);
 1709: 	if (rc < 0) {
 1710: 		ISTGT_ERRLOG("sigaction(SIGINFO) failed\n");
 1711: 		goto initialize_error;
 1712: 	}
 1713: #endif
 1714: #ifdef ISTGT_USE_SIGRT
 1715: 	if (ISTGT_SIGWAKEUP < SIGRTMIN
 1716: 		|| ISTGT_SIGWAKEUP > SIGRTMAX) {
 1717: 		ISTGT_ERRLOG("SIGRT error\n");
 1718: 		goto initialize_error;
 1719: 	}
 1720: #endif /* ISTGT_USE_SIGRT */
 1721: 	sigact.sa_handler = istgt_sigwakeup;
 1722: 	sigemptyset(&sigact.sa_mask);
 1723: 	rc = sigaction(ISTGT_SIGWAKEUP, &sigact, &sigoldact_wakeup);
 1724: 	if (rc < 0) {
 1725: 		ISTGT_ERRLOG("sigaction(ISTGT_SIGWAKEUP) failed\n");
 1726: 		goto initialize_error;
 1727: 	}
 1728: #ifdef SIGIO
 1729: 	sigact.sa_handler = istgt_sigio;
 1730: 	sigemptyset(&sigact.sa_mask);
 1731: 	rc = sigaction(SIGIO, &sigact, &sigoldact_io);
 1732: 	if (rc < 0) {
 1733: 		ISTGT_ERRLOG("sigaction(SIGIO) failed\n");
 1734: 		goto initialize_error;
 1735: 	}
 1736: #endif
 1737: 	pthread_sigmask(SIG_SETMASK, NULL, &signew);
 1738: 	sigaddset(&signew, SIGINT);
 1739: 	sigaddset(&signew, SIGTERM);
 1740: 	sigaddset(&signew, SIGQUIT);
 1741: 	sigaddset(&signew, SIGHUP);
 1742: #ifdef SIGINFO
 1743: 	sigaddset(&signew, SIGINFO);
 1744: #endif
 1745: 	sigaddset(&signew, SIGUSR1);
 1746: 	sigaddset(&signew, SIGUSR2);
 1747: #ifdef SIGIO
 1748: 	sigaddset(&signew, SIGIO);
 1749: #endif
 1750: 	sigaddset(&signew, ISTGT_SIGWAKEUP);
 1751: 	pthread_sigmask(SIG_SETMASK, &signew, &sigold);
 1752: #ifdef ISTGT_STACKSIZE
 1753: 	rc = pthread_create(&sigthread, &istgt->attr, &istgt_sighandler,
 1754: #else
 1755: 	rc = pthread_create(&sigthread, NULL, &istgt_sighandler,
 1756: #endif
 1757: 	    (void *) istgt);
 1758: 	if (rc != 0) {
 1759: 		ISTGT_ERRLOG("pthread_create() failed\n");
 1760: 		goto initialize_error;
 1761: 	}
 1762: #if 0
 1763: 	rc = pthread_detach(sigthread);
 1764: 	if (rc != 0) {
 1765: 		ISTGT_ERRLOG("pthread_detach() failed\n");
 1766: 		goto initialize_error;
 1767: 	}
 1768: #endif
 1769: #ifdef HAVE_PTHREAD_SET_NAME_NP
 1770: 	pthread_set_name_np(sigthread, "sigthread");
 1771: 	pthread_set_name_np(pthread_self(), "mainthread");
 1772: #endif
 1773: 
 1774: 	/* create LUN threads for command queuing */
 1775: 	rc = istgt_lu_create_threads(istgt);
 1776: 	if (rc < 0) {
 1777: 		ISTGT_ERRLOG("lu_create_threads() failed\n");
 1778: 		goto initialize_error;
 1779: 	}
 1780: 	rc = istgt_lu_set_all_state(istgt, ISTGT_STATE_RUNNING);
 1781: 	if (rc < 0) {
 1782: 		ISTGT_ERRLOG("lu_set_all_state() failed\n");
 1783: 		goto initialize_error;
 1784: 	}
 1785: 
 1786: 	/* open portals */
 1787: 	rc = istgt_open_uctl_portal(istgt);
 1788: 	if (rc < 0) {
 1789: 		ISTGT_ERRLOG("istgt_open_uctl_portal() failed\n");
 1790: 		goto initialize_error;
 1791: 	}
 1792: 	rc = istgt_open_portal(istgt);
 1793: 	if (rc < 0) {
 1794: 		ISTGT_ERRLOG("istgt_open_portal() failed\n");
 1795: 		goto initialize_error;
 1796: 	}
 1797: 
 1798: 	/* write pid */
 1799: 	rc = istgt_write_pidfile(istgt);
 1800: 	if (rc < 0) {
 1801: 		ISTGT_ERRLOG("istgt_write_pid() failed\n");
 1802: 		goto initialize_error;
 1803: 	}
 1804: 
 1805: 	/* accept loop */
 1806: 	rc = istgt_acceptor(istgt);
 1807: 	if (rc < 0) {
 1808: 		ISTGT_ERRLOG("istgt_acceptor() failed\n");
 1809: 		istgt_close_portal(istgt);
 1810: 		istgt_close_uctl_portal(istgt);
 1811: 		istgt_iscsi_shutdown(istgt);
 1812: 		istgt_lu_shutdown(istgt);
 1813: 		istgt_destory_initiator_group_array(istgt);
 1814: 		istgt_destroy_portal_array(istgt);
 1815: 		istgt_destroy_uctl_portal(istgt);
 1816: 		istgt_remove_pidfile(istgt);
 1817: 		istgt_close_log();
 1818: 		istgt->config = NULL;
 1819: 		istgt_free_config(config);
 1820: 		exit(EXIT_FAILURE);
 1821: 	}
 1822: 
 1823: 	/* wait threads */
 1824: 	while (retry > 0) {
 1825: 		if (istgt_get_active_conns() == 0) {
 1826: 			break;
 1827: 		}
 1828: 		sleep(1);
 1829: 		retry--;
 1830: 	}
 1831: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "retry=%d\n", retry);
 1832: 
 1833: 	ISTGT_NOTICELOG("istgt version %s (%s) exiting\n", ISTGT_VERSION,
 1834: 	    ISTGT_EXTRA_VERSION);
 1835: 
 1836: 	/* cleanup */
 1837: 	istgt_close_portal(istgt);
 1838: 	istgt_close_uctl_portal(istgt);
 1839: 	istgt_iscsi_shutdown(istgt);
 1840: 	istgt_lu_shutdown(istgt);
 1841: 	istgt_destory_initiator_group_array(istgt);
 1842: 	istgt_destroy_portal_array(istgt);
 1843: 	istgt_destroy_uctl_portal(istgt);
 1844: 	istgt_remove_pidfile(istgt);
 1845: 	istgt_close_log();
 1846: 	istgt->config = NULL;
 1847: 	istgt_free_config(config);
 1848: 	istgt_set_state(istgt, ISTGT_STATE_SHUTDOWN);
 1849: 
 1850: 	/* stop signal thread */
 1851: 	rc = pthread_join(sigthread, NULL);
 1852: 	if (rc != 0) {
 1853: 		ISTGT_ERRLOG("pthread_join() failed\n");
 1854: 		exit (EXIT_FAILURE);
 1855: 	}
 1856: 
 1857: 	return 0;
 1858: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>