File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / istgt / src / istgt.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:13:23 2012 UTC (11 years, 10 months ago) by misho
Branches: istgt, MAIN
CVS tags: v20121028, v20120901, HEAD
dhcp 4.1 r7

    1: /*
    2:  * Copyright (C) 2008-2012 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: #if !defined(__GNUC__)
   71: #undef __attribute__
   72: #define __attribute__(x)
   73: #endif
   74: 
   75: #define POLLWAIT 5000
   76: #define PORTNUMLEN 32
   77: 
   78: ISTGT g_istgt;
   79: 
   80: static int
   81: istgt_parse_portal(const char *portal, char **host, char **port)
   82: {
   83: 	const char *p;
   84: 	int n;
   85: 
   86: 	if (portal == NULL) {
   87: 		ISTGT_ERRLOG("portal error\n");
   88: 		return -1;
   89: 	}
   90: 
   91: 	if (portal[0] == '[') {
   92: 		/* IPv6 */
   93: 		p = strchr(portal + 1, ']');
   94: 		if (p == NULL) {
   95: 			ISTGT_ERRLOG("portal error\n");
   96: 			return -1;
   97: 		}
   98: 		p++;
   99: 		n = p - portal;
  100: 		if (host != NULL) {
  101: 			*host = xmalloc(n + 1);
  102: 			memcpy(*host, portal, n);
  103: 			(*host)[n] = '\0';
  104: 		}
  105: 		if (p[0] == '\0') {
  106: 			if (port != NULL) {
  107: 				*port = xmalloc(PORTNUMLEN);
  108: 				snprintf(*port, PORTNUMLEN, "%d", DEFAULT_PORT);
  109: 			}
  110: 		} else {
  111: 			if (p[0] != ':') {
  112: 				ISTGT_ERRLOG("portal error\n");
  113: 				if (host != NULL)
  114: 					xfree(*host);
  115: 				return -1;
  116: 			}
  117: 			if (port != NULL)
  118: 				*port = xstrdup(p + 1);
  119: 		}
  120: 	} else {
  121: 		/* IPv4 */
  122: 		p = strchr(portal, ':');
  123: 		if (p == NULL) {
  124: 			p = portal + strlen(portal);
  125: 		}
  126: 		n = p - portal;
  127: 		if (host != NULL) {
  128: 			*host = xmalloc(n + 1);
  129: 			memcpy(*host, portal, n);
  130: 			(*host)[n] = '\0';
  131: 		}
  132: 		if (p[0] == '\0') {
  133: 			if (port != NULL) {
  134: 				*port = xmalloc(PORTNUMLEN);
  135: 				snprintf(*port, PORTNUMLEN, "%d", DEFAULT_PORT);
  136: 			}
  137: 		} else {
  138: 			if (p[0] != ':') {
  139: 				ISTGT_ERRLOG("portal error\n");
  140: 				if (host != NULL)
  141: 					xfree(*host);
  142: 				return -1;
  143: 			}
  144: 			if (port != NULL)
  145: 				*port = xstrdup(p + 1);
  146: 		}
  147: 	}
  148: 	return 0;
  149: }
  150: 
  151: static int
  152: istgt_add_portal_group(ISTGT_Ptr istgt, CF_SECTION *sp, int *pgp_idx)
  153: {
  154: 	const char *val;
  155: 	char *label, *portal, *host, *port;
  156: 	int alloc_len;
  157: 	int idx, free_idx;
  158: 	int portals;
  159: 	int rc;
  160: 	int i;
  161: 
  162: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "add portal group %d\n", sp->num);
  163: 
  164: 	val = istgt_get_val(sp, "Comment");
  165: 	if (val != NULL) {
  166: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Comment %s\n", val);
  167: 	}
  168: 
  169: 	/* counts number of definition */
  170: 	for (i = 0; ; i++) {
  171: 		label = istgt_get_nmval(sp, "Portal", i, 0);
  172: 		portal = istgt_get_nmval(sp, "Portal", i, 1);
  173: 		if (label == NULL || portal == NULL)
  174: 			break;
  175: 		rc = istgt_parse_portal(portal, NULL, NULL);
  176: 		if (rc < 0) {
  177: 			ISTGT_ERRLOG("parse portal error (%s)\n", portal);
  178: 			return -1;
  179: 		}
  180: 	}
  181: 	portals = i;
  182: 	if (portals > MAX_PORTAL) {
  183: 		ISTGT_ERRLOG("%d > MAX_PORTAL\n", portals);
  184: 		return -1;
  185: 	}
  186: 
  187: 	MTX_LOCK(&istgt->mutex);
  188: 	idx = istgt->nportal_group;
  189: 	free_idx = -1;
  190: 	for (i = 0; i < istgt->nportal_group; i++) {
  191: 		if (istgt->portal_group[i].tag != 0)
  192: 			continue;
  193: 		if (istgt->portal_group[i].nportals == portals) {
  194: 			free_idx = i;
  195: 			break;
  196: 		}
  197: 	}
  198: 	if (free_idx >= 0)
  199: 		idx = free_idx;
  200: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  201: 	    "Index=%d, Tag=%d, Portals=%d\n",
  202: 	    idx, sp->num, portals);
  203: 	if (idx < MAX_PORTAL_GROUP) {
  204: 		if (free_idx < 0) {
  205: 			istgt->portal_group[idx].nportals = portals;
  206: 			alloc_len = sizeof (PORTAL *) * portals;
  207: 			istgt->portal_group[idx].portals = xmalloc(alloc_len);
  208: 		}
  209: 		istgt->portal_group[idx].ref = 0;
  210: 		istgt->portal_group[idx].idx = idx;
  211: 		istgt->portal_group[idx].tag = sp->num;
  212: 
  213: 		for (i = 0; i < portals; i++) {
  214: 			label = istgt_get_nmval(sp, "Portal", i, 0);
  215: 			portal = istgt_get_nmval(sp, "Portal", i, 1);
  216: 			if (label == NULL || portal == NULL) {
  217: 				if (free_idx < 0) {
  218: 					xfree(istgt->portal_group[idx].portals);
  219: 					istgt->portal_group[idx].nportals = 0;
  220: 				}
  221: 				istgt->portal_group[idx].tag = 0;
  222: 				MTX_UNLOCK(&istgt->mutex);
  223: 				ISTGT_ERRLOG("portal error\n");
  224: 				return -1;
  225: 			}
  226: 			rc = istgt_parse_portal(portal, &host, &port);
  227: 			if (rc < 0) {
  228: 				if (free_idx < 0) {
  229: 					xfree(istgt->portal_group[idx].portals);
  230: 					istgt->portal_group[idx].nportals = 0;
  231: 				}
  232: 				istgt->portal_group[idx].tag = 0;
  233: 				MTX_UNLOCK(&istgt->mutex);
  234: 				ISTGT_ERRLOG("parse portal error (%s)\n", portal);
  235: 				return -1;
  236: 			}
  237: 			ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  238: 			    "RIndex=%d, Host=%s, Port=%s, Tag=%d\n",
  239: 			    i, host, port, sp->num);
  240: 
  241: 			if (free_idx < 0) {
  242: 				istgt->portal_group[idx].portals[i] = xmalloc(sizeof (PORTAL));
  243: 			} else {
  244: 				xfree(istgt->portal_group[idx].portals[i]->label);
  245: 				xfree(istgt->portal_group[idx].portals[i]->host);
  246: 				xfree(istgt->portal_group[idx].portals[i]->port);
  247: 			}
  248: 			istgt->portal_group[idx].portals[i]->label = xstrdup(label);
  249: 			istgt->portal_group[idx].portals[i]->host = host;
  250: 			istgt->portal_group[idx].portals[i]->port = port;
  251: 			istgt->portal_group[idx].portals[i]->ref = 0;
  252: 			istgt->portal_group[idx].portals[i]->idx = i;
  253: 			istgt->portal_group[idx].portals[i]->tag = sp->num;
  254: 			istgt->portal_group[idx].portals[i]->sock = -1;
  255:                 }
  256: 
  257: 		if (pgp_idx != NULL)
  258: 			*pgp_idx = idx;
  259: 		if (free_idx < 0) {
  260: 			idx++;
  261: 			istgt->nportal_group = idx;
  262: 		}
  263: 	} else {
  264: 		MTX_UNLOCK(&istgt->mutex);
  265: 		ISTGT_ERRLOG("nportal_group(%d) >= MAX_PORTAL_GROUP\n", idx);
  266: 		return -1;
  267: 	}
  268: 	MTX_UNLOCK(&istgt->mutex);
  269: 	return 0;
  270: }
  271: 
  272: static int
  273: istgt_pg_match_all(PORTAL_GROUP *pgp, CF_SECTION *sp)
  274: {
  275: 	char *label, *portal, *host, *port;
  276: 	int rc;
  277: 	int i;
  278: 
  279: 	for (i = 0; i < pgp->nportals; i++) {
  280: 		label = istgt_get_nmval(sp, "Portal", i, 0);
  281: 		portal = istgt_get_nmval(sp, "Portal", i, 1);
  282: 		if (label == NULL || portal == NULL)
  283: 			return 0;
  284: 		rc = istgt_parse_portal(portal, &host, &port);
  285: 		if (rc < 0)
  286: 			return 0;
  287: 		if (strcmp(pgp->portals[i]->label, label) != 0)
  288: 			return 0;
  289: 		if (strcmp(pgp->portals[i]->host, host) != 0)
  290: 			return 0;
  291: 		if (strcmp(pgp->portals[i]->port, port) != 0)
  292: 			return 0;
  293: 	}
  294: 	label = istgt_get_nmval(sp, "Portal", i, 0);
  295: 	portal = istgt_get_nmval(sp, "Portal", i, 1);
  296: 	if (label != NULL || portal != NULL)
  297: 		return 0;
  298: 	return 1;
  299: }
  300: 
  301: static int
  302: istgt_update_portal_group(ISTGT_Ptr istgt, CF_SECTION *sp, int *pgp_idx)
  303: {
  304: 	const char *val;
  305: 	char *label, *portal, *host, *port;
  306: 	int alloc_len;
  307: 	int idx, free_idx;
  308: 	int portals;
  309: 	int rc;
  310: 	int i;
  311: 
  312: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "update portal group %d\n", sp->num);
  313: 
  314: 	val = istgt_get_val(sp, "Comment");
  315: 	if (val != NULL) {
  316: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Comment %s\n", val);
  317: 	}
  318: 
  319: 	/* counts number of definition */
  320: 	for (i = 0; ; i++) {
  321: 		label = istgt_get_nmval(sp, "Portal", i, 0);
  322: 		portal = istgt_get_nmval(sp, "Portal", i, 1);
  323: 		if (label == NULL || portal == NULL)
  324: 			break;
  325: 		rc = istgt_parse_portal(portal, NULL, NULL);
  326: 		if (rc < 0) {
  327: 			ISTGT_ERRLOG("parse portal error (%s)\n", portal);
  328: 			return -1;
  329: 		}
  330: 	}
  331: 	portals = i;
  332: 	if (portals > MAX_PORTAL) {
  333: 		ISTGT_ERRLOG("%d > MAX_PORTAL\n", portals);
  334: 		return -1;
  335: 	}
  336: 
  337: 	MTX_LOCK(&istgt->mutex);
  338: 	idx = -1;
  339: 	for (i = 0; i < istgt->nportal_group; i++) {
  340: 		if (istgt->portal_group[i].tag == sp->num) {
  341: 			idx = i;
  342: 			break;
  343: 		}
  344: 	}
  345: 	if (idx < 0) {
  346: 		MTX_UNLOCK(&istgt->mutex);
  347: 		ISTGT_ERRLOG("can't find PG%d\n", sp->num);
  348: 		return -1;
  349: 	}
  350: 	if (istgt_pg_match_all(&istgt->portal_group[i], sp)) {
  351: 		MTX_UNLOCK(&istgt->mutex);
  352: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "skip for PG%d\n", sp->num);
  353: 		return 0;
  354: 	}
  355: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  356: 	    "Index=%d, Tag=%d, Portals=%d\n",
  357: 	    idx, sp->num, portals);
  358: 	if (istgt->portal_group[idx].nportals == portals) {
  359: 		/* udpate PG */
  360: 		for (i = 0; i < portals; i++) {
  361: 			label = istgt_get_nmval(sp, "Portal", i, 0);
  362: 			portal = istgt_get_nmval(sp, "Portal", i, 1);
  363: 			if (label == NULL || portal == NULL) {
  364: 				xfree(istgt->portal_group[idx].portals);
  365: 				istgt->portal_group[idx].nportals = 0;
  366: 				istgt->portal_group[idx].tag = 0;
  367: 				MTX_UNLOCK(&istgt->mutex);
  368: 				ISTGT_ERRLOG("portal error\n");
  369: 				return -1;
  370: 			}
  371: 			rc = istgt_parse_portal(portal, &host, &port);
  372: 			if (rc < 0) {
  373: 				xfree(istgt->portal_group[idx].portals);
  374: 				istgt->portal_group[idx].nportals = 0;
  375: 				istgt->portal_group[idx].tag = 0;
  376: 				MTX_UNLOCK(&istgt->mutex);
  377: 				ISTGT_ERRLOG("parse portal error (%s)\n", portal);
  378: 				return -1;
  379: 			}
  380: 			ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  381: 			    "RIndex=%d, Host=%s, Port=%s, Tag=%d\n",
  382: 			    i, host, port, sp->num);
  383: 
  384: 			/* free old PG */
  385: 			xfree(istgt->portal_group[idx].portals[i]->label);
  386: 			xfree(istgt->portal_group[idx].portals[i]->host);
  387: 			xfree(istgt->portal_group[idx].portals[i]->port);
  388: 
  389: 			/* allocate new PG */
  390: 			istgt->portal_group[idx].portals[i]->label = xstrdup(label);
  391: 			istgt->portal_group[idx].portals[i]->host = host;
  392: 			istgt->portal_group[idx].portals[i]->port = port;
  393: 			//istgt->portal_group[idx].portals[i]->ref = 0;
  394: 			//istgt->portal_group[idx].portals[i]->idx = i;
  395: 			//istgt->portal_group[idx].portals[i]->tag = sp->num;
  396: 			//istgt->portal_group[idx].portals[i]->sock = -1;
  397:                 }
  398: 		if (pgp_idx != NULL)
  399: 			*pgp_idx = idx;
  400: 	} else {
  401: 		/* mark as free */
  402: 		istgt->portal_group[*pgp_idx].tag = 0;
  403: 
  404: 		/* allocate new PG */
  405: 		idx = istgt->nportal_group;
  406: 		free_idx = -1;
  407: 		for (i = 0; i < istgt->nportal_group; i++) {
  408: 			if (istgt->portal_group[i].tag != 0)
  409: 				continue;
  410: 			if (istgt->portal_group[i].nportals == portals) {
  411: 				free_idx = i;
  412: 				break;
  413: 			}
  414: 		}
  415: 		if (free_idx >= 0)
  416: 			idx = free_idx;
  417: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  418: 		    "Index=%d, Tag=%d, Portals=%d -> %d\n",
  419: 		    idx, sp->num, istgt->portal_group[*pgp_idx].nportals, portals);
  420: 		if (idx < MAX_PORTAL_GROUP) {
  421: 			if (free_idx < 0) {
  422: 				istgt->portal_group[idx].nportals = portals;
  423: 				alloc_len = sizeof (PORTAL *) * portals;
  424: 				istgt->portal_group[idx].portals = xmalloc(alloc_len);
  425: 			}
  426: 			istgt->portal_group[idx].ref = istgt->portal_group[*pgp_idx].ref;
  427: 			istgt->portal_group[idx].idx = idx;
  428: 			istgt->portal_group[idx].tag = sp->num;
  429: 
  430: 			for (i = 0; i < portals; i++) {
  431: 				label = istgt_get_nmval(sp, "Portal", i, 0);
  432: 				portal = istgt_get_nmval(sp, "Portal", i, 1);
  433: 				if (label == NULL || portal == NULL) {
  434: 					if (free_idx < 0) {
  435: 						xfree(istgt->portal_group[idx].portals);
  436: 						istgt->portal_group[idx].nportals = 0;
  437: 					}
  438: 					istgt->portal_group[idx].tag = 0;
  439: 					MTX_UNLOCK(&istgt->mutex);
  440: 					ISTGT_ERRLOG("portal error\n");
  441: 					return -1;
  442: 				}
  443: 				rc = istgt_parse_portal(portal, &host, &port);
  444: 				if (rc < 0) {
  445: 					if (free_idx < 0) {
  446: 						xfree(istgt->portal_group[idx].portals);
  447: 						istgt->portal_group[idx].nportals = 0;
  448: 					}
  449: 					istgt->portal_group[idx].tag = 0;
  450: 					MTX_UNLOCK(&istgt->mutex);
  451: 					ISTGT_ERRLOG("parse portal error (%s)\n", portal);
  452: 					return -1;
  453: 				}
  454: 				ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  455: 				    "RIndex=%d, Host=%s, Port=%s, Tag=%d\n",
  456: 				    i, host, port, sp->num);
  457: 
  458: 				if (free_idx < 0) {
  459: 					istgt->portal_group[idx].portals[i] = xmalloc(sizeof (PORTAL));
  460: 				} else {
  461: 					xfree(istgt->portal_group[idx].portals[i]->label);
  462: 					xfree(istgt->portal_group[idx].portals[i]->host);
  463: 					xfree(istgt->portal_group[idx].portals[i]->port);
  464: 				}
  465: 				istgt->portal_group[idx].portals[i]->label = xstrdup(label);
  466: 				istgt->portal_group[idx].portals[i]->host = host;
  467: 				istgt->portal_group[idx].portals[i]->port = port;
  468: 				istgt->portal_group[idx].portals[i]->ref = 0;
  469: 				istgt->portal_group[idx].portals[i]->idx = i;
  470: 				istgt->portal_group[idx].portals[i]->tag = sp->num;
  471: 				istgt->portal_group[idx].portals[i]->sock = -1;
  472: 			}
  473: 
  474: 			if (pgp_idx != NULL)
  475: 				*pgp_idx = idx;
  476: 			if (free_idx < 0) {
  477: 				idx++;
  478: 				istgt->nportal_group = idx;
  479: 			}
  480: 		} else {
  481: 			MTX_UNLOCK(&istgt->mutex);
  482: 			ISTGT_ERRLOG("nportal_group(%d) >= MAX_PORTAL_GROUP\n", idx);
  483: 			return -1;
  484: 		}
  485: 	}
  486: 	MTX_UNLOCK(&istgt->mutex);
  487: 	return 1;
  488: }
  489: 
  490: static int
  491: istgt_build_portal_group_array(ISTGT_Ptr istgt)
  492: {
  493: 	CF_SECTION *sp;
  494: 	int rc;
  495: 
  496: 	sp = istgt->config->section;
  497: 	while (sp != NULL) {
  498: 		if (sp->type == ST_PORTALGROUP) {
  499: 			if (sp->num == 0) {
  500: 				ISTGT_ERRLOG("Group 0 is invalid\n");
  501: 				return -1;
  502: 			}
  503: 			rc = istgt_add_portal_group(istgt, sp, NULL);
  504: 			if (rc < 0) {
  505: 				ISTGT_ERRLOG("add_portal_group() failed\n");
  506: 				return -1;
  507: 			}
  508: 		}
  509: 		sp = sp->next;
  510: 	}
  511: 	return 0;
  512: }
  513: 
  514: static void
  515: istgt_destroy_portal_group_array(ISTGT_Ptr istgt)
  516: {
  517: 	int i, j;
  518: 
  519: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_destory_portal_group_array\n");
  520: 	MTX_LOCK(&istgt->mutex);
  521: 	for (i = 0; i < istgt->nportal_group; i++) {
  522: 		for (j = 0; j < istgt->portal_group[i].nportals; j++) {
  523: 			xfree(istgt->portal_group[i].portals[j]->label);
  524: 			xfree(istgt->portal_group[i].portals[j]->host);
  525: 			xfree(istgt->portal_group[i].portals[j]->port);
  526: 			xfree(istgt->portal_group[i].portals[j]);
  527: 		}
  528: 		xfree(istgt->portal_group[i].portals);
  529: 
  530: 		istgt->portal_group[i].nportals = 0;
  531: 		istgt->portal_group[i].portals = NULL;
  532: 		istgt->portal_group[i].ref = 0;
  533: 		istgt->portal_group[i].idx = i;
  534: 		istgt->portal_group[i].tag = 0;
  535: 	}
  536: 	istgt->nportal_group = 0;
  537: 	MTX_UNLOCK(&istgt->mutex);
  538: }
  539: 
  540: static int
  541: istgt_open_portal_group(PORTAL_GROUP *pgp)
  542: {
  543: 	int port;
  544: 	int sock;
  545: 	int i;
  546: 
  547: 	for (i = 0; i < pgp->nportals; i++) {
  548: 		if (pgp->portals[i]->sock < 0) {
  549: 			ISTGT_TRACELOG(ISTGT_TRACE_NET, "open host %s, port %s, tag %d\n",
  550: 			    pgp->portals[i]->host, pgp->portals[i]->port,
  551: 			    pgp->portals[i]->tag);
  552: 			port = (int)strtol(pgp->portals[i]->port, NULL, 0);
  553: 			sock = istgt_listen(pgp->portals[i]->host, port);
  554: 			if (sock < 0) {
  555: 				ISTGT_ERRLOG("listen error %.64s:%d\n",
  556: 				    pgp->portals[i]->host, port);
  557: 				return -1;
  558: 			}
  559: 			pgp->portals[i]->sock = sock;
  560: 		}
  561: 	}
  562: 	return 0;
  563: }
  564: 
  565: static int
  566: istgt_open_all_portals(ISTGT_Ptr istgt)
  567: {
  568: 	int rc;
  569: 	int i;
  570: 
  571: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_open_portal\n");
  572: 	MTX_LOCK(&istgt->mutex);
  573: 	for (i = 0; i < istgt->nportal_group; i++) {
  574: 		rc = istgt_open_portal_group(&istgt->portal_group[i]);
  575: 		if (rc < 0) {
  576: 			MTX_UNLOCK(&istgt->mutex);
  577: 			return -1;
  578: 		}
  579: 	}
  580: 	MTX_UNLOCK(&istgt->mutex);
  581: 	return 0;
  582: }
  583: 
  584: static int
  585: istgt_close_portal_group(PORTAL_GROUP *pgp)
  586: {
  587: 	int i;
  588: 
  589: 	for (i = 0; i < pgp->nportals; i++) {
  590: 		if (pgp->portals[i]->sock >= 0) {
  591: 			ISTGT_TRACELOG(ISTGT_TRACE_NET, "close host %s, port %s, tag %d\n",
  592: 			    pgp->portals[i]->host, pgp->portals[i]->port,
  593: 			    pgp->portals[i]->tag);
  594: 			close(pgp->portals[i]->sock);
  595: 			pgp->portals[i]->sock = -1;
  596: 		}
  597: 	}
  598: 	return 0;
  599: }
  600: 
  601: static int
  602: istgt_close_all_portals(ISTGT_Ptr istgt)
  603: {
  604: 	int rc;
  605: 	int i;
  606: 
  607: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_close_portal\n");
  608: 	MTX_LOCK(&istgt->mutex);
  609: 	for (i = 0; i < istgt->nportal_group; i++) {
  610: 		rc = istgt_close_portal_group(&istgt->portal_group[i]);
  611: 		if (rc < 0) {
  612: 			MTX_UNLOCK(&istgt->mutex);
  613: 			return -1;
  614: 		}
  615: 	}
  616: 	MTX_UNLOCK(&istgt->mutex);
  617: 	return 0;
  618: }
  619: 
  620: static int
  621: istgt_add_initiator_group(ISTGT_Ptr istgt, CF_SECTION *sp)
  622: {
  623: 	const char *val;
  624: 	int alloc_len;
  625: 	int idx;
  626: 	int names;
  627: 	int masks;
  628: 	int i;
  629: 
  630: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "add initiator group %d\n", sp->num);
  631: 
  632: 	val = istgt_get_val(sp, "Comment");
  633: 	if (val != NULL) {
  634: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Comment %s\n", val);
  635: 	}
  636: 
  637: 	/* counts number of definition */
  638: 	for (i = 0; ; i++) {
  639: 		val = istgt_get_nval(sp, "InitiatorName", i);
  640: 		if (val == NULL)
  641: 			break;
  642: 	}
  643: 	names = i;
  644: 	if (names > MAX_INITIATOR) {
  645: 		ISTGT_ERRLOG("%d > MAX_INITIATOR\n", names);
  646: 		return -1;
  647: 	}
  648: 	for (i = 0; ; i++) {
  649: 		val = istgt_get_nval(sp, "Netmask", i);
  650: 		if (val == NULL)
  651: 			break;
  652: 	}
  653: 	masks = i;
  654: 	if (masks > MAX_NETMASK) {
  655: 		ISTGT_ERRLOG("%d > MAX_NETMASK\n", masks);
  656: 		return -1;
  657: 	}
  658: 
  659: 	MTX_LOCK(&istgt->mutex);
  660: 	idx = istgt->ninitiator_group;
  661: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  662: 	    "Index=%d, Tag=%d, Names=%d, Masks=%d\n",
  663: 	    idx, sp->num, names, masks);
  664: 	if (idx < MAX_INITIATOR_GROUP) {
  665: 		istgt->initiator_group[idx].ninitiators = names;
  666: 		alloc_len = sizeof (char *) * names;
  667: 		istgt->initiator_group[idx].initiators = xmalloc(alloc_len);
  668: 		istgt->initiator_group[idx].nnetmasks = masks;
  669: 		alloc_len = sizeof (char *) * masks;
  670: 		istgt->initiator_group[idx].netmasks = xmalloc(alloc_len);
  671: 		istgt->initiator_group[idx].ref = 0;
  672: 		istgt->initiator_group[idx].idx = idx;
  673: 		istgt->initiator_group[idx].tag = sp->num;
  674: 
  675: 		for (i = 0; i < names; i++) {
  676: 			val = istgt_get_nval(sp, "InitiatorName", i);
  677: 			ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  678: 			    "InitiatorName %s\n", val);
  679: 			istgt->initiator_group[idx].initiators[i] = xstrdup(val);
  680: 		}
  681: 		for (i = 0; i < masks; i++) {
  682: 			val = istgt_get_nval(sp, "Netmask", i);
  683: 			ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Netmask %s\n", val);
  684: 			istgt->initiator_group[idx].netmasks[i] = xstrdup(val);
  685: 		}
  686: 
  687: 		idx++;
  688: 		istgt->ninitiator_group = idx;
  689: 	} else {
  690: 		MTX_UNLOCK(&istgt->mutex);
  691: 		ISTGT_ERRLOG("ninitiator_group(%d) >= MAX_INITIATOR_GROUP\n", idx);
  692: 		return -1;
  693: 	}
  694: 	MTX_UNLOCK(&istgt->mutex);
  695: 	return 0;
  696: }
  697: 
  698: static int
  699: istgt_ig_match_all(INITIATOR_GROUP *igp, CF_SECTION *sp)
  700: {
  701: 	const char *val;
  702: 	int i;
  703: 
  704: 	for (i = 0; i < igp->ninitiators; i++) {
  705: 		val = istgt_get_nval(sp, "InitiatorName", i);
  706: 		if (val == NULL)
  707: 			return 0;
  708: 		if (strcmp(igp->initiators[i], val) != 0)
  709: 			return 0;
  710: 	}
  711: 	val = istgt_get_nval(sp, "InitiatorName", i);
  712: 	if (val != NULL)
  713: 		return 0;
  714: 	for (i = 0; i < igp->nnetmasks; i++) {
  715: 		val = istgt_get_nval(sp, "Netmask", i);
  716: 		if (val == NULL)
  717: 			return 0;
  718: 		if (strcmp(igp->netmasks[i], val) != 0)
  719: 			return 0;
  720: 	}
  721: 	val = istgt_get_nval(sp, "Netmask", i);
  722: 	if (val != NULL)
  723: 		return 0;
  724: 	return 1;
  725: }
  726: 
  727: static int
  728: istgt_update_initiator_group(ISTGT_Ptr istgt, CF_SECTION *sp)
  729: {
  730: 	const char *val;
  731: 	int alloc_len;
  732: 	int idx;
  733: 	int names;
  734: 	int masks;
  735: 	int i;
  736: 
  737: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "update initiator group %d\n", sp->num);
  738: 
  739: 	val = istgt_get_val(sp, "Comment");
  740: 	if (val != NULL) {
  741: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Comment %s\n", val);
  742: 	}
  743: 
  744: 	/* counts number of definition */
  745: 	for (i = 0; ; i++) {
  746: 		val = istgt_get_nval(sp, "InitiatorName", i);
  747: 		if (val == NULL)
  748: 			break;
  749: 	}
  750: 	names = i;
  751: 	if (names > MAX_INITIATOR) {
  752: 		ISTGT_ERRLOG("%d > MAX_INITIATOR\n", names);
  753: 		return -1;
  754: 	}
  755: 	for (i = 0; ; i++) {
  756: 		val = istgt_get_nval(sp, "Netmask", i);
  757: 		if (val == NULL)
  758: 			break;
  759: 	}
  760: 	masks = i;
  761: 	if (masks > MAX_NETMASK) {
  762: 		ISTGT_ERRLOG("%d > MAX_NETMASK\n", masks);
  763: 		return -1;
  764: 	}
  765: 
  766: 	MTX_LOCK(&istgt->mutex);
  767: 	idx = -1;
  768: 	for (i = 0; i < istgt->ninitiator_group; i++) {
  769: 		if (istgt->initiator_group[i].tag == sp->num) {
  770: 			idx = i;
  771: 			break;
  772: 		}
  773: 	}
  774: 	if (idx < 0) {
  775: 		MTX_UNLOCK(&istgt->mutex);
  776: 		ISTGT_ERRLOG("can't find IG%d\n", sp->num);
  777: 		return -1;
  778: 	}
  779: 	if (istgt_ig_match_all(&istgt->initiator_group[i], sp)) {
  780: 		MTX_UNLOCK(&istgt->mutex);
  781: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "skip for IG%d\n", sp->num);
  782: 		return 0;
  783: 	}
  784: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  785: 	    "Index=%d, Tag=%d, Names=%d, Masks=%d\n",
  786: 	    idx, sp->num, names, masks);
  787: 
  788: 	/* free old IG */
  789: 	for (i = 0; i < istgt->initiator_group[idx].ninitiators; i++) {
  790: 		xfree(istgt->initiator_group[idx].initiators[i]);
  791: 	}
  792: 	xfree(istgt->initiator_group[idx].initiators);
  793: 	for (i = 0; i < istgt->initiator_group[idx].nnetmasks; i++) {
  794: 		xfree(istgt->initiator_group[idx].netmasks[i]);
  795: 	}
  796: 	xfree(istgt->initiator_group[idx].netmasks);
  797: 
  798: 	/* allocate new IG */
  799: 	istgt->initiator_group[idx].ninitiators = names;
  800: 	alloc_len = sizeof (char *) * names;
  801: 	istgt->initiator_group[idx].initiators = xmalloc(alloc_len);
  802: 	istgt->initiator_group[idx].nnetmasks = masks;
  803: 	alloc_len = sizeof (char *) * masks;
  804: 	istgt->initiator_group[idx].netmasks = xmalloc(alloc_len);
  805: 	//istgt->initiator_group[idx].ref = 0;
  806: 	//istgt->initiator_group[idx].idx = idx;
  807: 	//istgt->initiator_group[idx].tag = sp->num;
  808: 
  809: 	/* copy new strings */
  810: 	for (i = 0; i < names; i++) {
  811: 		val = istgt_get_nval(sp, "InitiatorName", i);
  812: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  813: 		    "InitiatorName %s\n", val);
  814: 		istgt->initiator_group[idx].initiators[i] = xstrdup(val);
  815: 	}
  816: 	for (i = 0; i < masks; i++) {
  817: 		val = istgt_get_nval(sp, "Netmask", i);
  818: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Netmask %s\n", val);
  819: 		istgt->initiator_group[idx].netmasks[i] = xstrdup(val);
  820: 	}
  821: 	MTX_UNLOCK(&istgt->mutex);
  822: 	return 1;
  823: }
  824: 
  825: static int
  826: istgt_build_initiator_group_array(ISTGT_Ptr istgt)
  827: {
  828: 	CF_SECTION *sp;
  829: 	int rc;
  830: 
  831: 	sp = istgt->config->section;
  832: 	while (sp != NULL) {
  833: 		if (sp->type == ST_INITIATORGROUP) {
  834: 			if (sp->num == 0) {
  835: 				ISTGT_ERRLOG("Group 0 is invalid\n");
  836: 				return -1;
  837: 			}
  838: 			rc = istgt_add_initiator_group(istgt, sp);
  839: 			if (rc < 0) {
  840: 				ISTGT_ERRLOG("add_initiator_group() failed\n");
  841: 				return -1;
  842: 			}
  843: 		}
  844: 		sp = sp->next;
  845: 	}
  846: 	return 0;
  847: }
  848: 
  849: static void
  850: istgt_destory_initiator_group_array(ISTGT_Ptr istgt)
  851: {
  852: 	int i, j;
  853: 
  854: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_destory_initiator_group_array\n");
  855: 	MTX_LOCK(&istgt->mutex);
  856: 	for (i = 0; i < istgt->ninitiator_group; i++) {
  857: 		for (j = 0; j < istgt->initiator_group[i].ninitiators; j++) {
  858: 			xfree(istgt->initiator_group[i].initiators[j]);
  859: 		}
  860: 		xfree(istgt->initiator_group[i].initiators);
  861: 		for (j = 0; j < istgt->initiator_group[i].nnetmasks; j++) {
  862: 			xfree(istgt->initiator_group[i].netmasks[j]);
  863: 		}
  864: 		xfree(istgt->initiator_group[i].netmasks);
  865: 
  866: 		istgt->initiator_group[i].ninitiators = 0;
  867: 		istgt->initiator_group[i].initiators = NULL;
  868: 		istgt->initiator_group[i].nnetmasks = 0;
  869: 		istgt->initiator_group[i].netmasks = NULL;
  870: 		istgt->initiator_group[i].ref = 0;
  871: 		istgt->initiator_group[i].idx = i;
  872: 		istgt->initiator_group[i].tag = 0;
  873: 	}
  874: 	istgt->ninitiator_group = 0;
  875: 	MTX_UNLOCK(&istgt->mutex);
  876: }
  877: 
  878: static int
  879: istgt_build_uctl_portal(ISTGT_Ptr istgt)
  880: {
  881: 	CF_SECTION *sp;
  882: 	const char *val;
  883: 	char *label, *portal, *host, *port;
  884: 	int tag;
  885: 	int idx;
  886: 	int rc;
  887: 	int i;
  888: 
  889: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_build_uctl_portal\n");
  890: 
  891: 	sp = istgt_find_cf_section(istgt->config, "UnitControl");
  892: 	if (sp == NULL) {
  893: 		ISTGT_ERRLOG("find_cf_section failed()\n");
  894: 		return -1;
  895: 	}
  896: 
  897: 	for (i = 0; ; i++) {
  898: 		val = istgt_get_nval(sp, "Portal", i);
  899: 		if (val == NULL)
  900: 			break;
  901: 
  902: 		label = istgt_get_nmval(sp, "Portal", i, 0);
  903: 		portal = istgt_get_nmval(sp, "Portal", i, 1);
  904: 		if (label == NULL || portal == NULL) {
  905: 			ISTGT_ERRLOG("uctl portal error\n");
  906: 			return -1;
  907: 		}
  908: 
  909: 		rc = istgt_parse_portal(portal, &host, &port);
  910: 		if (rc < 0) {
  911: 			ISTGT_ERRLOG("parse uctl portal error\n");
  912: 			return -1;
  913: 		}
  914: 
  915: 		idx = istgt->nuctl_portal;
  916: 		tag = ISTGT_UC_TAG;
  917: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
  918: 		    "Index=%d, Host=%s, Port=%s, Tag=%d\n",
  919: 		    idx, host, port, tag);
  920: 		if (idx < MAX_UCPORTAL) {
  921: 			istgt->uctl_portal[idx].label = xstrdup(label);
  922: 			istgt->uctl_portal[idx].host = host;
  923: 			istgt->uctl_portal[idx].port = port;
  924: 			istgt->uctl_portal[idx].ref = 0;
  925: 			istgt->uctl_portal[idx].idx = idx;
  926: 			istgt->uctl_portal[idx].tag = tag;
  927: 			istgt->uctl_portal[idx].sock = -1;
  928: 			idx++;
  929: 			istgt->nuctl_portal = idx;
  930: 		} else {
  931: 			ISTGT_ERRLOG("nportal(%d) >= MAX_UCPORTAL\n", idx);
  932: 			xfree(host);
  933: 			xfree(port);
  934: 			return -1;
  935: 		}
  936: 	}
  937: 
  938: 	return 0;
  939: }
  940: 
  941: static void
  942: istgt_destroy_uctl_portal(ISTGT_Ptr istgt)
  943: {
  944: 	int i;
  945: 
  946: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_destroy_uctl_portal\n");
  947: 	for (i = 0; i < istgt->nuctl_portal; i++) {
  948: 		xfree(istgt->uctl_portal[i].label);
  949: 		xfree(istgt->uctl_portal[i].host);
  950: 		xfree(istgt->uctl_portal[i].port);
  951: 
  952: 		istgt->uctl_portal[i].label = NULL;
  953: 		istgt->uctl_portal[i].host = NULL;
  954: 		istgt->uctl_portal[i].port = NULL;
  955: 		istgt->uctl_portal[i].ref = 0;
  956: 		istgt->uctl_portal[i].idx = i;
  957: 		istgt->uctl_portal[i].tag = 0;
  958: 	}
  959: 	istgt->nuctl_portal = 0;
  960: }
  961: 
  962: static int
  963: istgt_open_uctl_portal(ISTGT_Ptr istgt)
  964: {
  965: 	int port;
  966: 	int sock;
  967: 	int i;
  968: 
  969: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_open_uctl_portal\n");
  970: 	for (i = 0; i < istgt->nuctl_portal; i++) {
  971: 		if (istgt->uctl_portal[i].sock < 0) {
  972: 			ISTGT_TRACELOG(ISTGT_TRACE_NET,
  973: 			    "open host %s, port %s, tag %d\n",
  974: 			    istgt->uctl_portal[i].host,
  975: 			    istgt->uctl_portal[i].port,
  976: 			    istgt->uctl_portal[i].tag);
  977: 			port = (int)strtol(istgt->uctl_portal[i].port, NULL, 0);
  978: 			sock = istgt_listen(istgt->uctl_portal[i].host, port);
  979: 			if (sock < 0) {
  980: 				ISTGT_ERRLOG("listen error %.64s:%d\n",
  981: 				    istgt->uctl_portal[i].host, port);
  982: 				return -1;
  983: 			}
  984: 			istgt->uctl_portal[i].sock = sock;
  985: 		}
  986: 	}
  987: 	return 0;
  988: }
  989: 
  990: static int
  991: istgt_close_uctl_portal(ISTGT_Ptr istgt)
  992: {
  993: 	int i;
  994: 
  995: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_close_uctl_portal\n");
  996: 	for (i = 0; i < istgt->nuctl_portal; i++) {
  997: 		if (istgt->uctl_portal[i].sock >= 0) {
  998: 			ISTGT_TRACELOG(ISTGT_TRACE_NET,
  999: 			    "close host %s, port %s, tag %d\n",
 1000: 			    istgt->uctl_portal[i].host,
 1001: 			    istgt->uctl_portal[i].port,
 1002: 			    istgt->uctl_portal[i].tag);
 1003: 			close(istgt->uctl_portal[i].sock);
 1004: 			istgt->uctl_portal[i].sock = -1;
 1005: 		}
 1006: 	}
 1007: 	return 0;
 1008: }
 1009: 
 1010: static int
 1011: istgt_write_pidfile(ISTGT_Ptr istgt)
 1012: {
 1013: 	FILE *fp;
 1014: 	pid_t pid;
 1015: 	int rc;
 1016: 
 1017: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_write_pidfile\n");
 1018: 	rc = remove(istgt->pidfile);
 1019: 	if (rc != 0) {
 1020: 		if (errno != ENOENT) {
 1021: 			ISTGT_ERRLOG("pidfile remove error %d\n", errno);
 1022: 			return -1;
 1023: 		}
 1024: 	}
 1025: 	fp = fopen(istgt->pidfile, "w");
 1026: 	if (fp == NULL) {
 1027: 		ISTGT_ERRLOG("pidfile open error %d\n", errno);
 1028: 		return -1;
 1029: 	}
 1030: 	pid = getpid();
 1031: 	fprintf(fp, "%d\n", (int)pid);
 1032: 	fclose(fp);
 1033: 	return 0;
 1034: }
 1035: 
 1036: static void
 1037: istgt_remove_pidfile(ISTGT_Ptr istgt)
 1038: {
 1039: 	int rc;
 1040: 
 1041: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_remove_pidfile\n");
 1042: 	rc = remove(istgt->pidfile);
 1043: 	if (rc != 0) {
 1044: 		ISTGT_ERRLOG("pidfile remove error %d\n", errno);
 1045: 		/* ignore error */
 1046: 	}
 1047: }
 1048: 
 1049: char *
 1050: istgt_get_nmval(CF_SECTION *sp, const char *key, int idx1, int idx2)
 1051: {
 1052: 	CF_ITEM *ip;
 1053: 	CF_VALUE *vp;
 1054: 	int i;
 1055: 
 1056: 	ip = istgt_find_cf_nitem(sp, key, idx1);
 1057: 	if (ip == NULL)
 1058: 		return NULL;
 1059: 	vp = ip->val;
 1060: 	if (vp == NULL)
 1061: 		return NULL;
 1062: 	for (i = 0; vp != NULL; vp = vp->next) {
 1063: 		if (i == idx2)
 1064: 			return vp->value;
 1065: 		i++;
 1066: 	}
 1067: 	return NULL;
 1068: }
 1069: 
 1070: char *
 1071: istgt_get_nval(CF_SECTION *sp, const char *key, int idx)
 1072: {
 1073: 	CF_ITEM *ip;
 1074: 	CF_VALUE *vp;
 1075: 
 1076: 	ip = istgt_find_cf_nitem(sp, key, idx);
 1077: 	if (ip == NULL)
 1078: 		return NULL;
 1079: 	vp = ip->val;
 1080: 	if (vp == NULL)
 1081: 		return NULL;
 1082: 	return vp->value;
 1083: }
 1084: 
 1085: char *
 1086: istgt_get_val(CF_SECTION *sp, const char *key)
 1087: {
 1088: 	return istgt_get_nval(sp, key, 0);
 1089: }
 1090: 
 1091: int
 1092: istgt_get_nintval(CF_SECTION *sp, const char *key, int idx)
 1093: {
 1094: 	const char *v;
 1095: 	int value;
 1096: 
 1097: 	v = istgt_get_nval(sp, key, idx);
 1098: 	if (v == NULL)
 1099: 		return -1;
 1100: 	value = (int)strtol(v, NULL, 10);
 1101: 	return value;
 1102: }
 1103: 
 1104: int
 1105: istgt_get_intval(CF_SECTION *sp, const char *key)
 1106: {
 1107: 	return istgt_get_nintval(sp, key, 0);
 1108: }
 1109: 
 1110: static const char *
 1111: istgt_get_log_facility(CONFIG *config)
 1112: {
 1113: 	CF_SECTION *sp;
 1114: 	const char *logfacility;
 1115: 
 1116: 	sp = istgt_find_cf_section(config, "Global");
 1117: 	if (sp == NULL) {
 1118: 		return NULL;
 1119: 	}
 1120: 	logfacility = istgt_get_val(sp, "LogFacility");
 1121: 	if (logfacility == NULL) {
 1122: 		logfacility = DEFAULT_LOG_FACILITY;
 1123: 	}
 1124: #if 0
 1125: 	if (g_trace_flag & ISTGT_TRACE_DEBUG) {
 1126: 		fprintf(stderr, "LogFacility %s\n", logfacility);
 1127: 	}
 1128: #endif
 1129: 
 1130: 	return logfacility;
 1131: }
 1132: 
 1133: static int
 1134: istgt_init(ISTGT_Ptr istgt)
 1135: {
 1136: 	CF_SECTION *sp;
 1137: 	const char *ag_tag;
 1138: 	const char *val;
 1139: 	size_t stacksize;
 1140: 	int ag_tag_i;
 1141: 	int MaxSessions;
 1142: 	int MaxConnections;
 1143: 	int MaxOutstandingR2T;
 1144: 	int DefaultTime2Wait;
 1145: 	int DefaultTime2Retain;
 1146: 	int FirstBurstLength;
 1147: 	int MaxBurstLength;
 1148: 	int MaxRecvDataSegmentLength;
 1149: 	int InitialR2T;
 1150: 	int ImmediateData;
 1151: 	int DataPDUInOrder;
 1152: 	int DataSequenceInOrder;
 1153: 	int ErrorRecoveryLevel;
 1154: 	int timeout;
 1155: 	int nopininterval;
 1156: 	int maxr2t;
 1157: 	int rc;
 1158: 	int i;
 1159: 
 1160: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_init\n");
 1161: 	sp = istgt_find_cf_section(istgt->config, "Global");
 1162: 	if (sp == NULL) {
 1163: 		ISTGT_ERRLOG("find_cf_section failed()\n");
 1164: 		return -1;
 1165: 	}
 1166: 
 1167: 	val = istgt_get_val(sp, "Comment");
 1168: 	if (val != NULL) {
 1169: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Comment %s\n", val);
 1170: 	}
 1171: 
 1172: 	val = istgt_get_val(sp, "PidFile");
 1173: 	if (val == NULL) {
 1174: 		val = DEFAULT_PIDFILE;
 1175: 	}
 1176: 	istgt->pidfile = xstrdup(val);
 1177: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "PidFile %s\n",
 1178: 	    istgt->pidfile);
 1179: 
 1180: 	val = istgt_get_val(sp, "AuthFile");
 1181: 	if (val == NULL) {
 1182: 		val = DEFAULT_AUTHFILE;
 1183: 	}
 1184: 	istgt->authfile = xstrdup(val);
 1185: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "AuthFile %s\n",
 1186: 	    istgt->authfile);
 1187: 
 1188: #if 0
 1189: 	val = istgt_get_val(sp, "MediaFile");
 1190: 	if (val == NULL) {
 1191: 		val = DEFAULT_MEDIAFILE;
 1192: 	}
 1193: 	istgt->mediafile = xstrdup(val);
 1194: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MediaFile %s\n",
 1195: 	    istgt->mediafile);
 1196: #endif
 1197: 
 1198: #if 0
 1199: 	val = istgt_get_val(sp, "LiveFile");
 1200: 	if (val == NULL) {
 1201: 		val = DEFAULT_LIVEFILE;
 1202: 	}
 1203: 	istgt->livefile = xstrdup(val);
 1204: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LiveFile %s\n",
 1205: 	    istgt->livefile);
 1206: #endif
 1207: 
 1208: 	val = istgt_get_val(sp, "MediaDirectory");
 1209: 	if (val == NULL) {
 1210: 		val = DEFAULT_MEDIADIRECTORY;
 1211: 	}
 1212: 	istgt->mediadirectory = xstrdup(val);
 1213: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MediaDirectory %s\n",
 1214: 	    istgt->mediadirectory);
 1215: 
 1216: 	val = istgt_get_val(sp, "NodeBase");
 1217: 	if (val == NULL) {
 1218: 		val = DEFAULT_NODEBASE;
 1219: 	}
 1220: 	istgt->nodebase = xstrdup(val);
 1221: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "NodeBase %s\n",
 1222: 	    istgt->nodebase);
 1223: 
 1224: 	MaxSessions = istgt_get_intval(sp, "MaxSessions");
 1225: 	if (MaxSessions < 1) {
 1226: 		MaxSessions = DEFAULT_MAX_SESSIONS;
 1227: 	}
 1228: 	istgt->MaxSessions = MaxSessions;
 1229: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxSessions %d\n",
 1230: 	    istgt->MaxSessions);
 1231: 
 1232: 	MaxConnections = istgt_get_intval(sp, "MaxConnections");
 1233: 	if (MaxConnections < 1) {
 1234: 		MaxConnections = DEFAULT_MAX_CONNECTIONS;
 1235: 	}
 1236: 	istgt->MaxConnections = MaxConnections;
 1237: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxConnections %d\n",
 1238: 	    istgt->MaxConnections);
 1239: 
 1240: 	/* limited to 16bits - RFC3720(12.2) */
 1241: 	if (MaxSessions > 0xffff) {
 1242: 		ISTGT_ERRLOG("over 65535 sessions are not supported\n");
 1243: 		return -1;
 1244: 	}
 1245: 	if (MaxConnections > 0xffff) {
 1246: 		ISTGT_ERRLOG("over 65535 connections are not supported\n");
 1247: 		return -1;
 1248: 	}
 1249: 
 1250: 	MaxOutstandingR2T = istgt_get_intval(sp, "MaxOutstandingR2T");
 1251: 	if (MaxOutstandingR2T < 1) {
 1252: 		MaxOutstandingR2T = DEFAULT_MAXOUTSTANDINGR2T;
 1253: 	}
 1254: 	istgt->MaxOutstandingR2T = MaxOutstandingR2T;
 1255: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxOutstandingR2T %d\n",
 1256: 	    istgt->MaxOutstandingR2T);
 1257: 
 1258: 	DefaultTime2Wait = istgt_get_intval(sp, "DefaultTime2Wait");
 1259: 	if (DefaultTime2Wait < 0) {
 1260: 		DefaultTime2Wait = DEFAULT_DEFAULTTIME2WAIT;
 1261: 	}
 1262: 	istgt->DefaultTime2Wait = DefaultTime2Wait;
 1263: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DefaultTime2Wait %d\n",
 1264: 	    istgt->DefaultTime2Wait);
 1265: 
 1266: 	DefaultTime2Retain = istgt_get_intval(sp, "DefaultTime2Retain");
 1267: 	if (DefaultTime2Retain < 0) {
 1268: 		DefaultTime2Retain = DEFAULT_DEFAULTTIME2RETAIN;
 1269: 	}
 1270: 	istgt->DefaultTime2Retain = DefaultTime2Retain;
 1271: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DefaultTime2Retain %d\n",
 1272: 	    istgt->DefaultTime2Retain);
 1273: 
 1274: 	/* check size limit - RFC3720(12.15, 12.16, 12.17) */
 1275: 	if (istgt->MaxOutstandingR2T > 65535) {
 1276: 		ISTGT_ERRLOG("MaxOutstandingR2T(%d) > 65535\n",
 1277: 		    istgt->MaxOutstandingR2T);
 1278: 		return -1;
 1279: 	}
 1280: 	if (istgt->DefaultTime2Wait > 3600) {
 1281: 		ISTGT_ERRLOG("DefaultTime2Wait(%d) > 3600\n",
 1282: 		    istgt->DefaultTime2Wait);
 1283: 		return -1;
 1284: 	}
 1285: 	if (istgt->DefaultTime2Retain > 3600) {
 1286: 		ISTGT_ERRLOG("DefaultTime2Retain(%d) > 3600\n",
 1287: 		    istgt->DefaultTime2Retain);
 1288: 		return -1;
 1289: 	}
 1290: 
 1291: 	FirstBurstLength = istgt_get_intval(sp, "FirstBurstLength");
 1292: 	if (FirstBurstLength < 0) {
 1293: 		FirstBurstLength = DEFAULT_FIRSTBURSTLENGTH;
 1294: 	}
 1295: 	istgt->FirstBurstLength = FirstBurstLength;
 1296: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "FirstBurstLength %d\n",
 1297: 	    istgt->FirstBurstLength);
 1298: 
 1299: 	MaxBurstLength = istgt_get_intval(sp, "MaxBurstLength");
 1300: 	if (MaxBurstLength < 0) {
 1301: 		MaxBurstLength = DEFAULT_MAXBURSTLENGTH;
 1302: 	}
 1303: 	istgt->MaxBurstLength = MaxBurstLength;
 1304: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxBurstLength %d\n",
 1305: 	    istgt->MaxBurstLength);
 1306: 
 1307: 	MaxRecvDataSegmentLength
 1308: 		= istgt_get_intval(sp, "MaxRecvDataSegmentLength");
 1309: 	if (MaxRecvDataSegmentLength < 0) {
 1310: 		MaxRecvDataSegmentLength = DEFAULT_MAXRECVDATASEGMENTLENGTH;
 1311: 	}
 1312: 	istgt->MaxRecvDataSegmentLength = MaxRecvDataSegmentLength;
 1313: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxRecvDataSegmentLength %d\n",
 1314: 	    istgt->MaxRecvDataSegmentLength);
 1315: 
 1316: 	/* check size limit (up to 24bits - RFC3720(12.12)) */
 1317: 	if (istgt->MaxBurstLength < 512) {
 1318: 		ISTGT_ERRLOG("MaxBurstLength(%d) < 512\n",
 1319: 		    istgt->MaxBurstLength);
 1320: 		return -1;
 1321: 	}
 1322: 	if (istgt->FirstBurstLength < 512) {
 1323: 		ISTGT_ERRLOG("FirstBurstLength(%d) < 512\n",
 1324: 		    istgt->FirstBurstLength);
 1325: 		return -1;
 1326: 	}
 1327: 	if (istgt->FirstBurstLength > istgt->MaxBurstLength) {
 1328: 		ISTGT_ERRLOG("FirstBurstLength(%d) > MaxBurstLength(%d)\n",
 1329: 		    istgt->FirstBurstLength, istgt->MaxBurstLength);
 1330: 		return -1;
 1331: 	}
 1332: 	if (istgt->MaxBurstLength > 0x00ffffff) {
 1333: 		ISTGT_ERRLOG("MaxBurstLength(%d) > 0x00ffffff\n",
 1334: 		    istgt->MaxBurstLength);
 1335: 		return -1;
 1336: 	}
 1337: 	if (istgt->MaxRecvDataSegmentLength < 512) {
 1338: 		ISTGT_ERRLOG("MaxRecvDataSegmentLength(%d) < 512\n",
 1339: 		    istgt->MaxRecvDataSegmentLength);
 1340: 		return -1;
 1341: 	}
 1342: 	if (istgt->MaxRecvDataSegmentLength > 0x00ffffff) {
 1343: 		ISTGT_ERRLOG("MaxRecvDataSegmentLength(%d) > 0x00ffffff\n",
 1344: 		    istgt->MaxRecvDataSegmentLength);
 1345: 		return -1;
 1346: 	}
 1347: 
 1348: 	val = istgt_get_val(sp, "InitialR2T");
 1349: 	if (val == NULL) {
 1350: 		InitialR2T = DEFAULT_INITIALR2T;
 1351: 	} else if (strcasecmp(val, "Yes") == 0) {
 1352: 		InitialR2T = 1;
 1353: 	} else if (strcasecmp(val, "No") == 0) {
 1354: #if 0
 1355: 		InitialR2T = 0;
 1356: #else
 1357: 		ISTGT_ERRLOG("not supported value %s\n", val);
 1358: 		return -1;
 1359: #endif
 1360: 	} else {
 1361: 		ISTGT_ERRLOG("unknown value %s\n", val);
 1362: 		return -1;
 1363: 	}
 1364: 	istgt->InitialR2T = InitialR2T;
 1365: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "InitialR2T %s\n",
 1366: 	    istgt->InitialR2T ? "Yes" : "No");
 1367: 
 1368: 	val = istgt_get_val(sp, "ImmediateData");
 1369: 	if (val == NULL) {
 1370: 		ImmediateData = DEFAULT_IMMEDIATEDATA;
 1371: 	} else if (strcasecmp(val, "Yes") == 0) {
 1372: 		ImmediateData = 1;
 1373: 	} else if (strcasecmp(val, "No") == 0) {
 1374: 		ImmediateData = 0;
 1375: 	} else {
 1376: 		ISTGT_ERRLOG("unknown value %s\n", val);
 1377: 		return -1;
 1378: 	}
 1379: 	istgt->ImmediateData = ImmediateData;
 1380: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "ImmediateData %s\n",
 1381: 	    istgt->ImmediateData ? "Yes" : "No");
 1382: 
 1383: 	val = istgt_get_val(sp, "DataPDUInOrder");
 1384: 	if (val == NULL) {
 1385: 		DataPDUInOrder = DEFAULT_DATAPDUINORDER;
 1386: 	} else if (strcasecmp(val, "Yes") == 0) {
 1387: 		DataPDUInOrder = 1;
 1388: 	} else if (strcasecmp(val, "No") == 0) {
 1389: #if 0
 1390: 		DataPDUInOrder = 0;
 1391: #else
 1392: 		ISTGT_ERRLOG("not supported value %s\n", val);
 1393: 		return -1;
 1394: #endif
 1395: 	} else {
 1396: 		ISTGT_ERRLOG("unknown value %s\n", val);
 1397: 		return -1;
 1398: 	}
 1399: 	istgt->DataPDUInOrder = DataPDUInOrder;
 1400: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DataPDUInOrder %s\n",
 1401: 	    istgt->DataPDUInOrder ? "Yes" : "No");
 1402: 
 1403: 	val = istgt_get_val(sp, "DataSequenceInOrder");
 1404: 	if (val == NULL) {
 1405: 		DataSequenceInOrder = DEFAULT_DATASEQUENCEINORDER;
 1406: 	} else if (strcasecmp(val, "Yes") == 0) {
 1407: 		DataSequenceInOrder = 1;
 1408: 	} else if (strcasecmp(val, "No") == 0) {
 1409: #if 0
 1410: 		DataSequenceInOrder = 0;
 1411: #else
 1412: 		ISTGT_ERRLOG("not supported value %s\n", val);
 1413: 		return -1;
 1414: #endif
 1415: 	} else {
 1416: 		ISTGT_ERRLOG("unknown value %s\n", val);
 1417: 		return -1;
 1418: 	}
 1419: 	istgt->DataSequenceInOrder = DataSequenceInOrder;
 1420: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DataSequenceInOrder %s\n",
 1421: 	    istgt->DataSequenceInOrder ? "Yes" : "No");
 1422: 
 1423: 	ErrorRecoveryLevel = istgt_get_intval(sp, "ErrorRecoveryLevel");
 1424: 	if (ErrorRecoveryLevel < 0) {
 1425: 		ErrorRecoveryLevel = DEFAULT_ERRORRECOVERYLEVEL;
 1426: 	} else if (ErrorRecoveryLevel == 0) {
 1427: 		ErrorRecoveryLevel = 0;
 1428: 	} else if (ErrorRecoveryLevel == 1) {
 1429: #if 0
 1430: 		ErrorRecoveryLevel = 1;
 1431: #else
 1432: 		ISTGT_ERRLOG("not supported value %d\n", ErrorRecoveryLevel);
 1433: 		return -1;
 1434: #endif
 1435: 	} else if (ErrorRecoveryLevel == 2) {
 1436: #if 0
 1437: 		ErrorRecoveryLevel = 2;
 1438: #else
 1439: 		ISTGT_ERRLOG("not supported value %d\n", ErrorRecoveryLevel);
 1440: 		return -1;
 1441: #endif
 1442: 	} else {
 1443: 		ISTGT_ERRLOG("not supported value %d\n", ErrorRecoveryLevel);
 1444: 		return -1;
 1445: 	}
 1446: 	istgt->ErrorRecoveryLevel = ErrorRecoveryLevel;
 1447: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "ErrorRecoveryLevel %d\n",
 1448: 	    istgt->ErrorRecoveryLevel);
 1449: 
 1450: 	timeout = istgt_get_intval(sp, "Timeout");
 1451: 	if (timeout < 0) {
 1452: 		timeout = DEFAULT_TIMEOUT;
 1453: 	}
 1454: 	istgt->timeout = timeout;
 1455: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Timeout %d\n",
 1456: 	    istgt->timeout);
 1457: 
 1458: 	nopininterval = istgt_get_intval(sp, "NopInInterval");
 1459: 	if (nopininterval < 0) {
 1460: 		nopininterval = DEFAULT_NOPININTERVAL;
 1461: 	}
 1462: 	istgt->nopininterval = nopininterval;
 1463: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "NopInInterval %d\n",
 1464: 	    istgt->nopininterval);
 1465: 
 1466: 	maxr2t = istgt_get_intval(sp, "MaxR2T");
 1467: 	if (maxr2t < 0) {
 1468: 		maxr2t = DEFAULT_MAXR2T;
 1469: 	}
 1470: 	if (maxr2t > MAX_R2T) {
 1471: 		ISTGT_ERRLOG("MaxR2T(%d) > %d\n",
 1472: 		    maxr2t, MAX_R2T);
 1473: 		return -1;
 1474: 	}
 1475: 	istgt->maxr2t = maxr2t;
 1476: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxR2T %d\n",
 1477: 	    istgt->maxr2t);
 1478: 
 1479: 	val = istgt_get_val(sp, "DiscoveryAuthMethod");
 1480: 	if (val == NULL) {
 1481: 		istgt->no_discovery_auth = 0;
 1482: 		istgt->req_discovery_auth = 0;
 1483: 		istgt->req_discovery_auth_mutual = 0;
 1484: 	} else {
 1485: 		istgt->no_discovery_auth = 0;
 1486: 		for (i = 0; ; i++) {
 1487: 			val = istgt_get_nmval(sp, "DiscoveryAuthMethod", 0, i);
 1488: 			if (val == NULL)
 1489: 				break;
 1490: 			if (strcasecmp(val, "CHAP") == 0) {
 1491: 				istgt->req_discovery_auth = 1;
 1492: 			} else if (strcasecmp(val, "Mutual") == 0) {
 1493: 				istgt->req_discovery_auth_mutual = 1;
 1494: 			} else if (strcasecmp(val, "Auto") == 0) {
 1495: 				istgt->req_discovery_auth = 0;
 1496: 				istgt->req_discovery_auth_mutual = 0;
 1497: 			} else if (strcasecmp(val, "None") == 0) {
 1498: 				istgt->no_discovery_auth = 1;
 1499: 				istgt->req_discovery_auth = 0;
 1500: 				istgt->req_discovery_auth_mutual = 0;
 1501: 			} else {
 1502: 				ISTGT_ERRLOG("unknown auth\n");
 1503: 				return -1;
 1504: 			}
 1505: 		}
 1506: 		if (istgt->req_discovery_auth_mutual && !istgt->req_discovery_auth) {
 1507: 			ISTGT_ERRLOG("Mutual but not CHAP\n");
 1508: 			return -1;
 1509: 		}
 1510: 	}
 1511: 	if (istgt->no_discovery_auth != 0) {
 1512: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 1513: 		    "DiscoveryAuthMethod None\n");
 1514: 	} else if (istgt->req_discovery_auth == 0) {
 1515: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 1516: 		    "DiscoveryAuthMethod Auto\n");
 1517: 	} else {
 1518: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 1519: 		    "DiscoveryAuthMethod %s %s\n",
 1520: 		    istgt->req_discovery_auth ? "CHAP" : "",
 1521: 		    istgt->req_discovery_auth_mutual ? "Mutual" : "");
 1522: 	}
 1523: 
 1524: 	val = istgt_get_val(sp, "DiscoveryAuthGroup");
 1525: 	if (val == NULL) {
 1526: 		istgt->discovery_auth_group = 0;
 1527: 	} else {
 1528: 		ag_tag = val;
 1529: 		if (strcasecmp(ag_tag, "None") == 0) {
 1530: 			ag_tag_i = 0;
 1531: 		} else {
 1532: 			if (strncasecmp(ag_tag, "AuthGroup",
 1533: 				strlen("AuthGroup")) != 0
 1534: 			    || sscanf(ag_tag, "%*[^0-9]%d", &ag_tag_i) != 1) {
 1535: 				ISTGT_ERRLOG("auth group error\n");
 1536: 				return -1;
 1537: 			}
 1538: 			if (ag_tag_i == 0) {
 1539: 				ISTGT_ERRLOG("invalid auth group %d\n",
 1540: 				    ag_tag_i);
 1541: 				return -1;
 1542: 			}
 1543: 		}
 1544: 		istgt->discovery_auth_group = ag_tag_i;
 1545: 	}
 1546: 	if (istgt->discovery_auth_group == 0) {
 1547: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 1548: 		    "DiscoveryAuthGroup None\n");
 1549: 	} else {
 1550: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 1551: 		    "DiscoveryAuthGroup AuthGroup%d\n",
 1552: 		    istgt->discovery_auth_group);
 1553: 	}
 1554: 
 1555: 	rc = istgt_uctl_init(istgt);
 1556: 	if (rc < 0) {
 1557: 		ISTGT_ERRLOG("istgt_uctl_init() failed\n");
 1558: 		return -1;
 1559: 	}
 1560: 	rc = istgt_build_uctl_portal(istgt);
 1561: 	if (rc < 0) {
 1562: 		ISTGT_ERRLOG("istgt_build_uctl_portal() failed\n");
 1563: 		return -1;
 1564: 	}
 1565: 	rc = istgt_build_portal_group_array(istgt);
 1566: 	if (rc < 0) {
 1567: 		ISTGT_ERRLOG("istgt_build_portal_array() failed\n");
 1568: 		return -1;
 1569: 	}
 1570: 	rc = istgt_build_initiator_group_array(istgt);
 1571: 	if (rc < 0) {
 1572: 		ISTGT_ERRLOG("build_initiator_group_array() failed\n");
 1573: 		return -1;
 1574: 	}
 1575: 
 1576: 	rc = pthread_attr_init(&istgt->attr);
 1577: 	if (rc != 0) {
 1578: 		ISTGT_ERRLOG("pthread_attr_init() failed\n");
 1579: 		return -1;
 1580: 	}
 1581: 	rc = pthread_attr_getstacksize(&istgt->attr, &stacksize);
 1582: 	if (rc != 0) {
 1583: 		ISTGT_ERRLOG("pthread_attr_getstacksize() failed\n");
 1584: 		return -1;
 1585: 	}
 1586: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "current thread stack = %zd\n", stacksize);
 1587: 	if (stacksize < ISTGT_STACKSIZE) {
 1588: 		stacksize = ISTGT_STACKSIZE;
 1589: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "new thread stack = %zd\n", stacksize);
 1590: 		rc = pthread_attr_setstacksize(&istgt->attr, stacksize);
 1591: 		if (rc != 0) {
 1592: 			ISTGT_ERRLOG("pthread_attr_setstacksize() failed\n");
 1593: 			return -1;
 1594: 		}
 1595: 	}
 1596: 
 1597: 	rc = pthread_mutexattr_init(&istgt->mutex_attr);
 1598: 	if (rc != 0) {
 1599: 		ISTGT_ERRLOG("mutexattr_init() failed\n");
 1600: 		return -1;
 1601: 	}
 1602: #ifdef HAVE_PTHREAD_MUTEX_ADAPTIVE_NP
 1603: 	rc = pthread_mutexattr_settype(&istgt->mutex_attr, PTHREAD_MUTEX_ADAPTIVE_NP);
 1604: #else
 1605: 	rc = pthread_mutexattr_settype(&istgt->mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
 1606: #endif
 1607: 	if (rc != 0) {
 1608: 		ISTGT_ERRLOG("mutexattr_settype() failed\n");
 1609: 		return -1;
 1610: 	}
 1611: 	rc = pthread_mutex_init(&istgt->mutex, NULL);
 1612: 	if (rc != 0) {
 1613: 		ISTGT_ERRLOG("mutex_init() failed\n");
 1614: 		return -1;
 1615: 	}
 1616: 	rc = pthread_mutex_init(&istgt->state_mutex, &istgt->mutex_attr);
 1617: 	if (rc != 0) {
 1618: 		ISTGT_ERRLOG("mutex_init() failed\n");
 1619: 		return -1;
 1620: 	}
 1621: 	rc = pthread_mutex_init(&istgt->reload_mutex, &istgt->mutex_attr);
 1622: 	if (rc != 0) {
 1623: 		ISTGT_ERRLOG("mutex_init() failed\n");
 1624: 		return -1;
 1625: 	}
 1626: 	rc = pthread_cond_init(&istgt->reload_cond, NULL);
 1627: 	if (rc != 0) {
 1628: 		ISTGT_ERRLOG("cond_init() failed\n");
 1629: 		return -1;
 1630: 	}
 1631: 
 1632: 	rc = pipe(istgt->sig_pipe);
 1633: 	if (rc != 0) {
 1634: 		ISTGT_ERRLOG("pipe() failed\n");
 1635: 		istgt->sig_pipe[0] = -1;
 1636: 		istgt->sig_pipe[1] = -1;
 1637: 		return -1;
 1638: 	}
 1639: 
 1640: 	/* XXX TODO: add initializer */
 1641: 
 1642: 	istgt_set_state(istgt, ISTGT_STATE_INITIALIZED);
 1643: 
 1644: 	return 0;
 1645: }
 1646: 
 1647: static void
 1648: istgt_shutdown(ISTGT_Ptr istgt)
 1649: {
 1650: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_shutdown\n");
 1651: 
 1652: 	istgt_destory_initiator_group_array(istgt);
 1653: 	istgt_destroy_portal_group_array(istgt);
 1654: 	istgt_destroy_uctl_portal(istgt);
 1655: 	istgt_uctl_shutdown(istgt);
 1656: 	istgt_remove_pidfile(istgt);
 1657: 	xfree(istgt->pidfile);
 1658: 	xfree(istgt->authfile);
 1659: #if 0
 1660: 	xfree(istgt->mediafile);
 1661: 	xfree(istgt->livefile);
 1662: #endif
 1663: 	xfree(istgt->mediadirectory);
 1664: 	xfree(istgt->nodebase);
 1665: 
 1666: 	if (istgt->sig_pipe[0] != -1)
 1667: 	    close(istgt->sig_pipe[0]);
 1668: 	if (istgt->sig_pipe[1] != -1)
 1669: 	    close(istgt->sig_pipe[1]);
 1670: 
 1671: 	(void) pthread_cond_destroy(&istgt->reload_cond);
 1672: 	(void) pthread_mutex_destroy(&istgt->reload_mutex);
 1673: 	(void) pthread_mutex_destroy(&istgt->state_mutex);
 1674: 	(void) pthread_mutex_destroy(&istgt->mutex);
 1675: 	(void) pthread_attr_destroy(&istgt->attr);
 1676: }
 1677: 
 1678: static int
 1679: istgt_pg_exist_num(CONFIG *config, int num)
 1680: {
 1681: 	CF_SECTION *sp;
 1682: 
 1683: 	sp = config->section;
 1684: 	while (sp != NULL) {
 1685: 		if (sp->type == ST_PORTALGROUP) {
 1686: 			if (sp->num == num) {
 1687: 				return 1;
 1688: 			}
 1689: 		}
 1690: 		sp = sp->next;
 1691: 	}
 1692: 	return -1;
 1693: }
 1694: 
 1695: static PORTAL_GROUP *
 1696: istgt_get_tag_portal(ISTGT_Ptr istgt, int tag)
 1697: {
 1698: 	int i;
 1699: 
 1700: 	if (tag == 0)
 1701: 		return NULL;
 1702: 	MTX_LOCK(&istgt->mutex);
 1703: 	for (i = 0; i < istgt->nportal_group; i++) {
 1704: 		if (istgt->portal_group[i].tag == tag) {
 1705: 			MTX_UNLOCK(&istgt->mutex);
 1706: 			return &istgt->portal_group[i];
 1707: 		}
 1708: 	}
 1709: 	MTX_UNLOCK(&istgt->mutex);
 1710: 	return NULL;
 1711: }
 1712: 
 1713: #if 0
 1714: static int
 1715: istgt_get_num_of_portals(CF_SECTION *sp)
 1716: {
 1717: 	char *label, *portal;
 1718: 	int portals;
 1719: 	int rc;
 1720: 	int i;
 1721: 
 1722: 	for (i = 0; ; i++) {
 1723: 		label = istgt_get_nmval(sp, "Portal", i, 0);
 1724: 		portal = istgt_get_nmval(sp, "Portal", i, 1);
 1725: 		if (label == NULL || portal == NULL)
 1726: 			break;
 1727: 		rc = istgt_parse_portal(portal, NULL, NULL);
 1728: 		if (rc < 0) {
 1729: 			ISTGT_ERRLOG("parse portal error (%s)\n", portal);
 1730: 			return -1;
 1731: 		}
 1732: 	}
 1733: 	portals = i;
 1734: 	if (portals > MAX_PORTAL) {
 1735: 		ISTGT_ERRLOG("%d > MAX_PORTAL\n", portals);
 1736: 		return -1;
 1737: 	}
 1738: 	return portals;
 1739: }
 1740: #endif
 1741: 
 1742: #define RELOAD_CMD_LENGTH 5
 1743: static int
 1744: istgt_pg_reload_delete(ISTGT_Ptr istgt)
 1745: {
 1746: 	char tmp[RELOAD_CMD_LENGTH];
 1747: 	int rc;
 1748: 
 1749: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_pg_reload_delete\n");
 1750: 
 1751: 	istgt->pg_reload = 0;
 1752: 	/* request delete */
 1753: 	tmp[0] = 'D';
 1754: 	DSET32(&tmp[1], 0);
 1755: 	rc = write(istgt->sig_pipe[1], tmp, RELOAD_CMD_LENGTH);
 1756: 	if (rc < 0 || rc != RELOAD_CMD_LENGTH) {
 1757: 		ISTGT_ERRLOG("write() failed\n");
 1758: 		return -1;
 1759: 	}
 1760: 	/* wait for completion */
 1761: 	MTX_LOCK(&istgt->reload_mutex);
 1762: 	while (istgt->pg_reload == 0) {
 1763: 		pthread_cond_wait(&istgt->reload_cond, &istgt->reload_mutex);
 1764: 	}
 1765: 	rc = istgt->pg_reload;
 1766: 	MTX_UNLOCK(&istgt->reload_mutex);
 1767: 	if (rc < 0) {
 1768: 		if (istgt_get_state(istgt) != ISTGT_STATE_RUNNING) {
 1769: 			ISTGT_WARNLOG("pg_reload abort\n");
 1770: 			return -1;
 1771: 		}
 1772: 	}
 1773: 	return 0;
 1774: }
 1775: 
 1776: static int
 1777: istgt_pg_reload_update(ISTGT_Ptr istgt)
 1778: {
 1779: 	char tmp[RELOAD_CMD_LENGTH];
 1780: 	int rc;
 1781: 
 1782: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_pg_reload_update\n");
 1783: 
 1784: 	istgt->pg_reload = 0;
 1785: 	/* request update */
 1786: 	tmp[0] = 'U';
 1787: 	DSET32(&tmp[1], 0);
 1788: 	rc = write(istgt->sig_pipe[1], tmp, RELOAD_CMD_LENGTH);
 1789: 	if (rc < 0 || rc != RELOAD_CMD_LENGTH) {
 1790: 		ISTGT_ERRLOG("write() failed\n");
 1791: 		return -1;
 1792: 	}
 1793: 	/* wait for completion */
 1794: 	MTX_LOCK(&istgt->reload_mutex);
 1795: 	while (istgt->pg_reload == 0) {
 1796: 		pthread_cond_wait(&istgt->reload_cond, &istgt->reload_mutex);
 1797: 	}
 1798: 	rc = istgt->pg_reload;
 1799: 	MTX_UNLOCK(&istgt->reload_mutex);
 1800: 	if (rc < 0) {
 1801: 		if (istgt_get_state(istgt) != ISTGT_STATE_RUNNING) {
 1802: 			ISTGT_WARNLOG("pg_reload abort\n");
 1803: 			return -1;
 1804: 		}
 1805: 	}
 1806: 	return 0;
 1807: }
 1808: 
 1809: static int
 1810: istgt_ig_exist_num(CONFIG *config, int num)
 1811: {
 1812: 	CF_SECTION *sp;
 1813: 
 1814: 	sp = config->section;
 1815: 	while (sp != NULL) {
 1816: 		if (sp->type == ST_INITIATORGROUP) {
 1817: 			if (sp->num == num) {
 1818: 				return 1;
 1819: 			}
 1820: 		}
 1821: 		sp = sp->next;
 1822: 	}
 1823: 	return -1;
 1824: }
 1825: 
 1826: static int
 1827: istgt_ig_reload_delete(ISTGT_Ptr istgt)
 1828: {
 1829: 	INITIATOR_GROUP *igp;
 1830: 	int rc;
 1831: 	int i, j;
 1832: 
 1833: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_ig_reload_delete\n");
 1834: 	MTX_LOCK(&istgt->mutex);
 1835: 	for (i = 0; i < istgt->ninitiator_group; i++) {
 1836: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "IG reload idx=%d, (%d)\n",
 1837: 		    i, istgt->ninitiator_group);
 1838: 		igp = &istgt->initiator_group[i];
 1839: 		rc = istgt_ig_exist_num(istgt->config, igp->tag);
 1840: 		if (rc < 0) {
 1841: 			if (igp->ref != 0) {
 1842: 				ISTGT_ERRLOG("delete request for referenced IG%d\n",
 1843: 				    igp->tag);
 1844: 			} else {
 1845: 				ISTGT_NOTICELOG("delete IG%d\n", igp->tag);
 1846: 				/* free old IG */
 1847: 				for (j = 0; j < istgt->initiator_group[i].ninitiators; j++) {
 1848: 					xfree(istgt->initiator_group[i].initiators[j]);
 1849: 				}
 1850: 				xfree(istgt->initiator_group[i].initiators);
 1851: 				for (j = 0; j < istgt->initiator_group[i].nnetmasks; j++) {
 1852: 					xfree(istgt->initiator_group[i].netmasks[j]);
 1853: 				}
 1854: 				xfree(istgt->initiator_group[i].netmasks);
 1855: 
 1856: 				/* move from beyond the IG */
 1857: 				for (j = i; j < istgt->ninitiator_group - 1; j++) {
 1858: 					istgt->initiator_group[j].ninitiators
 1859: 						= istgt->initiator_group[j+1].ninitiators;
 1860: 					istgt->initiator_group[j].initiators
 1861: 						= istgt->initiator_group[j+1].initiators;
 1862: 					istgt->initiator_group[j].nnetmasks
 1863: 						= istgt->initiator_group[j+1].nnetmasks;
 1864: 					istgt->initiator_group[j].netmasks
 1865: 						= istgt->initiator_group[j+1].netmasks;
 1866: 					istgt->initiator_group[j].ref
 1867: 						= istgt->initiator_group[j+1].ref;
 1868: 					istgt->initiator_group[j].idx
 1869: 						= istgt->initiator_group[j+1].idx;
 1870: 					istgt->initiator_group[j].tag
 1871: 						= istgt->initiator_group[j+1].tag;
 1872: 				}
 1873: 				istgt->ninitiator_group--;
 1874: 			}
 1875: 		}
 1876: 	}
 1877: 	MTX_UNLOCK(&istgt->mutex);
 1878: 	return 0;
 1879: }
 1880: 
 1881: static int
 1882: istgt_ig_reload_update(ISTGT_Ptr istgt)
 1883: {
 1884: 	CF_SECTION *sp;
 1885: 	int rc;
 1886: 	int i;
 1887: 
 1888: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_ig_reload_update\n");
 1889: 	sp = istgt->config->section;
 1890: 	while (sp != NULL) {
 1891: 		if (sp->type == ST_INITIATORGROUP) {
 1892: 			if (sp->num == 0) {
 1893: 				ISTGT_ERRLOG("Group 0 is invalid\n");
 1894: 				goto skip_ig;
 1895: 			}
 1896: 			ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "IG reload tag=%d\n", sp->num);
 1897: #if 0
 1898: 			rc = istgt_ig_exist_num(istgt->config_old, sp->num);
 1899: #else
 1900: 			rc = -1;
 1901: 			MTX_LOCK(&istgt->mutex);
 1902: 			for (i = 0; i < istgt->ninitiator_group; i++) {
 1903: 				if (istgt->initiator_group[i].tag == sp->num) {
 1904: 					rc = 1;
 1905: 					break;
 1906: 				}
 1907: 			}
 1908: 			MTX_UNLOCK(&istgt->mutex);
 1909: #endif
 1910: 			if (rc < 0) {
 1911: 				rc = istgt_add_initiator_group(istgt, sp);
 1912: 				if (rc < 0) {
 1913: 					ISTGT_ERRLOG("add_initiator_group() failed\n");
 1914: 					goto skip_ig;
 1915: 				}
 1916: 				ISTGT_NOTICELOG("add IG%d\n", sp->num);
 1917: 			} else {
 1918: 				rc = istgt_update_initiator_group(istgt, sp);
 1919: 				if (rc < 0) {
 1920: 					ISTGT_ERRLOG("update_initiator_group() failed\n");
 1921: 					goto skip_ig;
 1922: 				} else if (rc == 0) {
 1923: 					// not modified
 1924: 				} else if (rc > 0) {
 1925: 					ISTGT_NOTICELOG("update IG%d\n", sp->num);
 1926: 				}
 1927: 			}
 1928: 		}
 1929: 	skip_ig:
 1930: 		sp = sp->next;
 1931: 	}
 1932: 	return 0;
 1933: }
 1934: 
 1935: static int
 1936: istgt_reload(ISTGT_Ptr istgt)
 1937: {
 1938: 	CONFIG *config_new, *config_old;
 1939: 	char *config_file;
 1940: 	int rc;
 1941: 
 1942: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_reload\n");
 1943: 	/* prepare config structure */
 1944: 	config_new = istgt_allocate_config();
 1945: 	config_old = istgt->config;
 1946: 	config_file = config_old->file;
 1947: 	rc = istgt_read_config(config_new, config_file);
 1948: 	if (rc < 0) {
 1949: 		ISTGT_ERRLOG("config error\n");
 1950: 		return -1;
 1951: 	}
 1952: 	if (config_new->section == NULL) {
 1953: 		ISTGT_ERRLOG("empty config\n");
 1954: 		istgt_free_config(config_new);
 1955: 		return -1;
 1956: 	}
 1957: 	istgt->config = config_new;
 1958: 	istgt->config_old = config_old;
 1959: 	istgt->generation++;
 1960: 
 1961: 	/* reload sub groups */
 1962: 	ISTGT_NOTICELOG("reload configuration #%"PRIu32"\n", istgt->generation);
 1963: 	rc = istgt_lu_reload_delete(istgt);
 1964: 	if (rc < 0) {
 1965: 		ISTGT_ERRLOG("LU reload del error\n");
 1966: 		return -1;
 1967: 	}
 1968: 	rc = istgt_ig_reload_delete(istgt);
 1969: 	if (rc < 0) {
 1970: 		ISTGT_ERRLOG("IG reload del error\n");
 1971: 		return -1;
 1972: 	}
 1973: 	rc = istgt_pg_reload_delete(istgt);
 1974: 	if (rc < 0) {
 1975: 		ISTGT_ERRLOG("PG reload del error\n");
 1976: 		return -1;
 1977: 	}
 1978: 
 1979: 	rc = istgt_pg_reload_update(istgt);
 1980: 	if (rc < 0) {
 1981: 		ISTGT_ERRLOG("PG reload add error\n");
 1982: 		return -1;
 1983: 	}
 1984: 	rc = istgt_ig_reload_update(istgt);
 1985: 	if (rc < 0) {
 1986: 		ISTGT_ERRLOG("IG reload add error\n");
 1987: 		return -1;
 1988: 	}
 1989: 	rc = istgt_lu_reload_update(istgt);
 1990: 	if (rc < 0) {
 1991: 		ISTGT_ERRLOG("LU reload add error\n");
 1992: 		return -1;
 1993: 	}
 1994: 
 1995: 	istgt->config_old = NULL;
 1996: 	istgt_free_config(config_old);
 1997: 	return 0;
 1998: }
 1999: 
 2000: static int
 2001: istgt_stop_loop(ISTGT_Ptr istgt)
 2002: {
 2003: 	char tmp[RELOAD_CMD_LENGTH];
 2004: 	int rc;
 2005: 
 2006: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_stop_loop\n");
 2007: 	tmp[0] = 'E';
 2008: 	DSET32(&tmp[1], 0);
 2009: 	rc = write(istgt->sig_pipe[1], tmp, RELOAD_CMD_LENGTH);
 2010: 	if (rc < 0 || rc != RELOAD_CMD_LENGTH) {
 2011: 		ISTGT_ERRLOG("write() failed\n");
 2012: 		/* ignore error */
 2013: 	}
 2014: 	return 0;
 2015: }
 2016: 
 2017: 
 2018: static void
 2019: istgt_sigint(int signo __attribute__((__unused__)))
 2020: {
 2021: }
 2022: 
 2023: static void
 2024: istgt_sigterm(int signo __attribute__((__unused__)))
 2025: {
 2026: }
 2027: 
 2028: static void
 2029: istgt_sighup(int signo __attribute__((__unused__)))
 2030: {
 2031: }
 2032: 
 2033: #ifdef SIGINFO
 2034: static void
 2035: istgt_siginfo(int signo __attribute__((__unused__)))
 2036: {
 2037: 	/* nothing */
 2038: }
 2039: #endif
 2040: 
 2041: static void
 2042: istgt_sigwakeup(int signo __attribute__((__unused__)))
 2043: {
 2044: }
 2045: 
 2046: #ifdef SIGIO
 2047: static void
 2048: istgt_sigio(int signo __attribute__((__unused__)))
 2049: {
 2050: }
 2051: #endif
 2052: 
 2053: static void *
 2054: istgt_sighandler(void *arg)
 2055: {
 2056: 	ISTGT_Ptr istgt = (ISTGT_Ptr) arg;
 2057: 	sigset_t signew;
 2058: 	int signo;
 2059: 
 2060: 	sigemptyset(&signew);
 2061: 	sigaddset(&signew, SIGINT);
 2062: 	sigaddset(&signew, SIGTERM);
 2063: 	sigaddset(&signew, SIGQUIT);
 2064: 	sigaddset(&signew, SIGHUP);
 2065: #ifdef SIGINFO
 2066: 	sigaddset(&signew, SIGINFO);
 2067: #endif
 2068: 	sigaddset(&signew, SIGUSR1);
 2069: 	sigaddset(&signew, SIGUSR2);
 2070: #ifdef SIGIO
 2071: 	sigaddset(&signew, SIGIO);
 2072: #endif
 2073: 
 2074: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop start\n");
 2075: 	while (1) {
 2076: 		if (istgt_get_state(istgt) == ISTGT_STATE_EXITING
 2077: 		    || istgt_get_state(istgt) == ISTGT_STATE_SHUTDOWN) {
 2078: 			break;
 2079: 		}
 2080: 		sigwait(&signew, &signo);
 2081: 		switch (signo) {
 2082: 		case SIGINT:
 2083: 			printf("SIGINT catch\n");
 2084: 			istgt_stop_loop(istgt);
 2085: 			istgt_set_state(istgt, ISTGT_STATE_EXITING);
 2086: 			istgt_lu_set_all_state(istgt, ISTGT_STATE_EXITING);
 2087: 			break;
 2088: 		case SIGTERM:
 2089: 			printf("SIGTERM catch\n");
 2090: 			istgt_stop_loop(istgt);
 2091: 			istgt_set_state(istgt, ISTGT_STATE_EXITING);
 2092: 			istgt_lu_set_all_state(istgt, ISTGT_STATE_EXITING);
 2093: 			break;
 2094: 		case SIGQUIT:
 2095: 			printf("SIGQUIT catch\n");
 2096: 			exit(EXIT_SUCCESS);
 2097: 			break;
 2098: 		case SIGHUP:
 2099: 			printf("SIGHUP catch\n");
 2100: 			istgt_reload(istgt);
 2101: 			break;
 2102: #ifdef SIGINFO
 2103: 		case SIGINFO:
 2104: 			printf("SIGINFO catch\n");
 2105: 			istgt_set_trace_flag(ISTGT_TRACE_ISCSI);
 2106: 			break;
 2107: #endif
 2108: 		case SIGUSR1:
 2109: 			printf("SIGUSR1 catch\n");
 2110: 			istgt_set_trace_flag(ISTGT_TRACE_NONE);
 2111: 			break;
 2112: 		case SIGUSR2:
 2113: 			printf("SIGUSR2 catch\n");
 2114: 			//istgt_set_trace_flag(ISTGT_TRACE_SCSI);
 2115: 			istgt_set_trace_flag(ISTGT_TRACE_ALL);
 2116: 			break;
 2117: #ifdef SIGIO
 2118: 		case SIGIO:
 2119: 			//printf("SIGIO catch\n");
 2120: 			break;
 2121: #endif
 2122: 		default:
 2123: 			break;
 2124: 		}
 2125: 	}
 2126: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop ended\n");
 2127: 
 2128: 	return NULL;
 2129: }
 2130: 
 2131: static PORTAL *
 2132: istgt_get_sock_portal(ISTGT_Ptr istgt, int sock)
 2133: {
 2134: 	int i, j;
 2135: 
 2136: 	if (sock < 0)
 2137: 		return NULL;
 2138: 	MTX_LOCK(&istgt->mutex);
 2139: 	for (i = 0; i < istgt->nportal_group; i++) {
 2140: 		for (j = 0; j < istgt->portal_group[i].nportals; j++) {
 2141: 			if (istgt->portal_group[i].portals[j]->sock == sock) {
 2142: 				MTX_UNLOCK(&istgt->mutex);
 2143: 				return istgt->portal_group[i].portals[j];
 2144: 			}
 2145: 		}
 2146: 	}
 2147: 	MTX_UNLOCK(&istgt->mutex);
 2148: 	return NULL;
 2149: }
 2150: 
 2151: static int
 2152: istgt_pg_delete(ISTGT_Ptr istgt)
 2153: {
 2154: 	PORTAL_GROUP *pgp;
 2155: 	int rc;
 2156: 	int i;
 2157: 
 2158: 	MTX_LOCK(&istgt->mutex);
 2159: 	for (i = 0; i < istgt->nportal_group; i++) {
 2160: 		pgp = &istgt->portal_group[i];
 2161: 		if (pgp->tag == 0)
 2162: 			continue;
 2163: 		ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "PG reload idx=%d, tag=%d, (%d)\n",
 2164: 		    i, pgp->tag, istgt->nportal_group);
 2165: 		rc = istgt_pg_exist_num(istgt->config, pgp->tag);
 2166: 		if (rc < 0) {
 2167: 			if (pgp->ref != 0) {
 2168: 				ISTGT_ERRLOG("delete request for referenced PG%d\n",
 2169: 				    pgp->tag);
 2170: 			} else {
 2171: 				ISTGT_NOTICELOG("delete PG%d\n", pgp->tag);
 2172: 				pgp->tag = 0;
 2173: 				(void) istgt_close_portal_group(pgp);
 2174: 			}
 2175: 		}
 2176: 	}
 2177: 	MTX_UNLOCK(&istgt->mutex);
 2178: 	return 0;
 2179: }
 2180: 
 2181: static int
 2182: istgt_pg_update(ISTGT_Ptr istgt)
 2183: {
 2184: 	PORTAL_GROUP *pgp;
 2185: 	CF_SECTION *sp;
 2186: 	int pgp_idx;
 2187: 	int rc;
 2188: 	int i;
 2189: 
 2190: 	sp = istgt->config->section;
 2191: 	while (sp != NULL) {
 2192: 		if (sp->type == ST_PORTALGROUP) {
 2193: 			if (sp->num == 0) {
 2194: 				ISTGT_ERRLOG("Group 0 is invalid\n");
 2195: 				goto skip_pg;
 2196: 			}
 2197: 			ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "PG reload tag=%d\n", sp->num);
 2198: #if 0
 2199: 			rc = istgt_pg_exist_num(istgt->config_old, sp->num);
 2200: #else
 2201: 			rc = -1;
 2202: 			MTX_LOCK(&istgt->mutex);
 2203: 			for (i = 0; i < istgt->nportal_group; i++) {
 2204: 				if (istgt->portal_group[i].tag == sp->num) {
 2205: 					rc = 1;
 2206: 					break;
 2207: 				}
 2208: 			}
 2209: 			MTX_UNLOCK(&istgt->mutex);
 2210: #endif
 2211: 			if (rc < 0) {
 2212: 				rc = istgt_add_portal_group(istgt, sp, &pgp_idx);
 2213: 				if (rc < 0) {
 2214: 					ISTGT_ERRLOG("add_portal_group() failed\n");
 2215: 					goto skip_pg;
 2216: 				}
 2217: 				MTX_LOCK(&istgt->mutex);
 2218: 				pgp = &istgt->portal_group[pgp_idx];
 2219: 				(void) istgt_open_portal_group(pgp);
 2220: 				MTX_UNLOCK(&istgt->mutex);
 2221: 				ISTGT_NOTICELOG("add PG%d\n", sp->num);
 2222: 			} else {
 2223: 				//portals = istgt_get_num_of_portals(sp);
 2224: 				pgp = istgt_get_tag_portal(istgt, sp->num);
 2225: 				if (istgt_pg_match_all(pgp, sp)) {
 2226: 					ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 2227: 					    "skip for PG%d\n", sp->num);
 2228: 				} else if (pgp->ref != 0) {
 2229: 					ISTGT_ERRLOG("update request for referenced PG%d\n",
 2230: 					    pgp->tag);
 2231: 				} else {
 2232: 					/* delete old sock */
 2233: 					MTX_LOCK(&istgt->mutex);
 2234: 					pgp_idx = pgp->idx;
 2235: 					(void) istgt_close_portal_group(pgp);
 2236: 					MTX_UNLOCK(&istgt->mutex);
 2237: 					rc = istgt_update_portal_group(istgt, sp, &pgp_idx);
 2238: 					if (rc < 0) {
 2239: 						ISTGT_ERRLOG("update_portal_group() failed\n");
 2240: 						goto skip_pg;
 2241: 					} else if (rc == 0) {
 2242: 						// not modified
 2243: 					} else if (rc > 0) {
 2244: 						/* add new sock */
 2245: 						MTX_LOCK(&istgt->mutex);
 2246: 						pgp = &istgt->portal_group[pgp_idx];
 2247: 						(void) istgt_open_portal_group(pgp);
 2248: 						MTX_UNLOCK(&istgt->mutex);
 2249: 						ISTGT_NOTICELOG("update PG%d\n", sp->num);
 2250: 					}
 2251: 				}
 2252: 			}
 2253: 		}
 2254: 	skip_pg:
 2255: 		sp = sp->next;
 2256: 	}
 2257: 	return 0;
 2258: }
 2259: 
 2260: static int
 2261: istgt_acceptor(ISTGT_Ptr istgt)
 2262: {
 2263: 	PORTAL *pp;
 2264: #ifdef ISTGT_USE_KQUEUE
 2265: 	int kq;
 2266: 	struct kevent kev;
 2267: 	struct timespec kev_timeout;
 2268: 	int kqsocks[MAX_PORTAL_GROUP + MAX_UCPORTAL];
 2269: #else
 2270: 	struct pollfd fds[MAX_PORTAL_GROUP + MAX_UCPORTAL];
 2271: #endif /* ISTGT_USE_KQUEUE */
 2272: 	struct sockaddr_storage sa;
 2273: 	socklen_t salen;
 2274: 	int sock;
 2275: 	int rc, n;
 2276: 	int ucidx;
 2277: 	int nidx;
 2278: 	int i, j;
 2279: 
 2280: 	if (istgt_get_state(istgt) != ISTGT_STATE_INITIALIZED) {
 2281: 		ISTGT_ERRLOG("not initialized\n");
 2282: 		return -1;
 2283: 	}
 2284: 	/* now running main thread */
 2285: 	istgt_set_state(istgt, ISTGT_STATE_RUNNING);
 2286: 
 2287: reload:
 2288: 	nidx = 0;
 2289: #ifdef ISTGT_USE_KQUEUE
 2290: 	kq = kqueue();
 2291: 	if (kq == -1) {
 2292: 		ISTGT_ERRLOG("kqueue() failed\n");
 2293: 		return -1;
 2294: 	}
 2295: 	for (i = 0; i < (int)(sizeof kqsocks / sizeof *kqsocks); i++) {
 2296: 		kqsocks[i] = -1;
 2297: 	}
 2298: 	MTX_LOCK(&istgt->mutex);
 2299: 	for (i = 0; i < istgt->nportal_group; i++) {
 2300: 		for (j = 0; j < istgt->portal_group[i].nportals; j++) {
 2301: 			if (istgt->portal_group[i].portals[j]->sock >= 0) {
 2302: 				ISTGT_EV_SET(&kev, istgt->portal_group[i].portals[j]->sock,
 2303: 				    EVFILT_READ, EV_ADD, 0, 0, NULL);
 2304: 				rc = kevent(kq, &kev, 1, NULL, 0, NULL);
 2305: 				if (rc == -1) {
 2306: 					MTX_UNLOCK(&istgt->mutex);
 2307: 					ISTGT_ERRLOG("kevent() failed\n");
 2308: 					close(kq);
 2309: 					return -1;
 2310: 				}
 2311: 				kqsocks[nidx] = istgt->portal_group[i].portals[j]->sock;
 2312: 				nidx++;
 2313: 			}
 2314: 		}
 2315: 	}
 2316: 	MTX_UNLOCK(&istgt->mutex);
 2317: 	ucidx = nidx;
 2318: 	for (i = 0; i < istgt->nuctl_portal; i++) {
 2319: 		ISTGT_EV_SET(&kev, istgt->uctl_portal[i].sock,
 2320: 		    EVFILT_READ, EV_ADD, 0, 0, NULL);
 2321: 		rc = kevent(kq, &kev, 1, NULL, 0, NULL);
 2322: 		if (rc == -1) {
 2323: 			ISTGT_ERRLOG("kevent() failed\n");
 2324: 			close(kq);
 2325: 			return -1;
 2326: 		}
 2327: 		kqsocks[nidx] = istgt->uctl_portal[i].sock;
 2328: 		nidx++;
 2329: 	}
 2330: 	ISTGT_EV_SET(&kev, istgt->sig_pipe[0], EVFILT_READ, EV_ADD, 0, 0, NULL);
 2331: 	rc = kevent(kq, &kev, 1, NULL, 0, NULL);
 2332: 	if (rc == -1) {
 2333: 		ISTGT_ERRLOG("kevent() failed\n");
 2334: 		close(kq);
 2335: 		return -1;
 2336: 	}
 2337: 	kqsocks[nidx] = istgt->sig_pipe[0];
 2338: 	nidx++;
 2339: 
 2340: 	if (!istgt->daemon) {
 2341: 		ISTGT_EV_SET(&kev, SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
 2342: 		rc = kevent(kq, &kev, 1, NULL, 0, NULL);
 2343: 		if (rc == -1) {
 2344: 			ISTGT_ERRLOG("kevent() failed\n");
 2345: 			close(kq);
 2346: 			return -1;
 2347: 		}
 2348: 		ISTGT_EV_SET(&kev, SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
 2349: 		rc = kevent(kq, &kev, 1, NULL, 0, NULL);
 2350: 		if (rc == -1) {
 2351: 			ISTGT_ERRLOG("kevent() failed\n");
 2352: 			close(kq);
 2353: 			return -1;
 2354: 		}
 2355: 	}
 2356: #else
 2357: 	memset(&fds, 0, sizeof fds);
 2358: 	MTX_LOCK(&istgt->mutex);
 2359: 	for (i = 0; i < istgt->nportal_group; i++) {
 2360: 		for (j = 0; j < istgt->portal_group[i].nportals; j++) {
 2361: 			if (istgt->portal_group[i].portals[j]->sock >= 0) {
 2362: 				fds[i].fd = istgt->portal_group[i].portals[j]->sock;
 2363: 				fds[i].events = POLLIN;
 2364: 				nidx++;
 2365: 			}
 2366: 		}
 2367: 	}
 2368: 	MTX_UNLOCK(&istgt->mutex);
 2369: 	ucidx = nidx;
 2370: 	for (i = 0; i < istgt->nuctl_portal; i++) {
 2371: 		fds[ucidx + i].fd = istgt->uctl_portal[i].sock;
 2372: 		fds[ucidx + i].events = POLLIN;
 2373: 		nidx++;
 2374: 	}
 2375: 	fds[nidx].fd = istgt->sig_pipe[0];
 2376: 	fds[nidx].events = POLLIN;
 2377: 	nidx++;
 2378: #endif /* ISTGT_USE_KQUEUE */
 2379: 
 2380: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop start\n");
 2381: 	while (1) {
 2382: 		if (istgt_get_state(istgt) != ISTGT_STATE_RUNNING) {
 2383: 			break;
 2384: 		}
 2385: #ifdef ISTGT_USE_KQUEUE
 2386: 		//ISTGT_TRACELOG(ISTGT_TRACE_NET, "kevent %d\n", nidx);
 2387: 		kev_timeout.tv_sec = 10;
 2388: 		kev_timeout.tv_nsec = 0;
 2389: 		rc = kevent(kq, NULL, 0, &kev, 1, &kev_timeout);
 2390: 		if (rc == -1 && errno == EINTR) {
 2391: 			continue;
 2392: 		}
 2393: 		if (rc == -1) {
 2394: 			ISTGT_ERRLOG("kevent() failed\n");
 2395: 			break;
 2396: 		}
 2397: 		if (rc == 0) {
 2398: 			/* idle timeout */
 2399: 			//ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "kevent TIMEOUT\n");
 2400: 			continue;
 2401: 		}
 2402: 		if (kev.filter == EVFILT_SIGNAL) {
 2403: 			ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "kevent SIGNAL\n");
 2404: 			if (kev.ident == SIGINT || kev.ident == SIGTERM) {
 2405: 				ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 2406: 				    "kevent SIGNAL SIGINT/SIGTERM\n");
 2407: 				break;
 2408: 			}
 2409: 			continue;
 2410: 		}
 2411: #else
 2412: 		//ISTGT_TRACELOG(ISTGT_TRACE_NET, "poll %d\n", nidx);
 2413: 		rc = poll(fds, nidx, POLLWAIT);
 2414: 		if (rc == -1 && errno == EINTR) {
 2415: 			continue;
 2416: 		}
 2417: 		if (rc == -1) {
 2418: 			ISTGT_ERRLOG("poll() failed\n");
 2419: 			break;
 2420: 		}
 2421: 		if (rc == 0) {
 2422: 			/* no fds */
 2423: 			//ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "poll TIMEOUT\n");
 2424: 			continue;
 2425: 		}
 2426: #endif /* ISTGT_USE_KQUEUE */
 2427: 
 2428: 		n = rc;
 2429: 		for (i = 0; n != 0 && i < ucidx; i++) {
 2430: #ifdef ISTGT_USE_KQUEUE
 2431: 			if (kev.ident == (uintptr_t)kqsocks[i]) {
 2432: 				if (kev.flags) {
 2433: 					ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 2434: 					    "flags %x\n",
 2435: 					    kev.flags);
 2436: 				}
 2437: #else
 2438: 			if (fds[i].revents) {
 2439: 				ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 2440: 				    "events %x\n",
 2441: 				    fds[i].revents);
 2442: 			}
 2443: 			if (fds[i].revents & POLLIN) {
 2444: #endif /* ISTGT_USE_KQUEUE */
 2445: 				n--;
 2446: 				memset(&sa, 0, sizeof(sa));
 2447: 				salen = sizeof(sa);
 2448: #ifdef ISTGT_USE_KQUEUE
 2449: 				ISTGT_TRACELOG(ISTGT_TRACE_NET, "accept %ld\n",
 2450: 				    (unsigned long)kev.ident);
 2451: 				pp = istgt_get_sock_portal(istgt, kev.ident);
 2452: 				rc = accept(kev.ident, (struct sockaddr *) &sa, &salen);
 2453: #else
 2454: 				ISTGT_TRACELOG(ISTGT_TRACE_NET, "accept %d\n",
 2455: 				    fds[i].fd);
 2456: 				pp = istgt_get_sock_portal(istgt, fds[i].fd);
 2457: 				rc = accept(fds[i].fd, (struct sockaddr *) &sa, &salen);
 2458: #endif /* ISTGT_USE_KQUEUE */
 2459: 				if (rc < 0) {
 2460: 					ISTGT_ERRLOG("accept error: %d\n", rc);
 2461: 					continue;
 2462: 				}
 2463: 				sock = rc;
 2464: #if 0
 2465: 				rc = fcntl(sock, F_GETFL, 0);
 2466: 				if (rc == -1) {
 2467: 					ISTGT_ERRLOG("fcntl() failed\n");
 2468: 					continue;
 2469: 				}
 2470: 				rc = fcntl(sock, F_SETFL, (rc | O_NONBLOCK));
 2471: 				if (rc == -1) {
 2472: 					ISTGT_ERRLOG("fcntl() failed\n");
 2473: 					continue;
 2474: 				}
 2475: #endif
 2476: 				rc = istgt_create_conn(istgt, pp, sock,
 2477: 				    (struct sockaddr *) &sa, salen);
 2478: 				if (rc < 0) {
 2479: 					close(sock);
 2480: 					ISTGT_ERRLOG("istgt_create_conn() failed\n");
 2481: 					continue;
 2482: 				}
 2483: 			}
 2484: 		}
 2485: 
 2486: 		/* check for control */
 2487: 		for (i = 0; n != 0 && i < istgt->nuctl_portal; i++) {
 2488: #ifdef ISTGT_USE_KQUEUE
 2489: 			if (kev.ident == (uintptr_t)istgt->uctl_portal[i].sock) {
 2490: 				if (kev.flags) {
 2491: 					ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 2492: 					    "flags %x\n",
 2493: 					    kev.flags);
 2494: 				}
 2495: #else
 2496: 			if (fds[ucidx + i].revents) {
 2497: 				ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 2498: 				    "events %x\n",
 2499: 				    fds[ucidx + i].revents);
 2500: 			}
 2501: 			if (fds[ucidx + i].revents & POLLIN) {
 2502: #endif /* ISTGT_USE_KQUEUE */
 2503: 				n--;
 2504: 				memset(&sa, 0, sizeof(sa));
 2505: 				salen = sizeof(sa);
 2506: #ifdef ISTGT_USE_KQUEUE
 2507: 				ISTGT_TRACELOG(ISTGT_TRACE_NET,
 2508: 				    "accept %ld\n", (unsigned long)kev.ident);
 2509: 				rc = accept(kev.ident,
 2510: 				    (struct sockaddr *) &sa, &salen);
 2511: #else
 2512: 				ISTGT_TRACELOG(ISTGT_TRACE_NET,
 2513: 				    "accept %d\n", fds[ucidx + i].fd);
 2514: 				rc = accept(fds[ucidx + i].fd,
 2515: 				    (struct sockaddr *) &sa, &salen);
 2516: #endif /* ISTGT_USE_KQUEUE */
 2517: 				if (rc < 0) {
 2518: 					ISTGT_ERRLOG("accept error: %d\n", rc);
 2519: 					continue;
 2520: 				}
 2521: 				sock = rc;
 2522: 				rc = istgt_create_uctl(istgt,
 2523: 				    &istgt->uctl_portal[i], sock,
 2524: 				    (struct sockaddr *) &sa, salen);
 2525: 				if (rc < 0) {
 2526: 					close(sock);
 2527: 					ISTGT_ERRLOG("istgt_create_uctl() failed\n");
 2528: 					continue;
 2529: 				}
 2530: 			}
 2531: 		}
 2532: 
 2533: 		/* check for signal thread */
 2534: #ifdef ISTGT_USE_KQUEUE
 2535: 		if (kev.ident == (uintptr_t)istgt->sig_pipe[0]) {
 2536: 			if (kev.flags & (EV_EOF|EV_ERROR)) {
 2537: 				ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 2538: 				    "kevent EOF/ERROR\n");
 2539: 				break;
 2540: 			}
 2541: #else
 2542: 		if (fds[nidx - 1].revents & POLLHUP) {
 2543: 			break;
 2544: 		}
 2545: 		if (fds[nidx - 1].revents & POLLIN) {
 2546: #endif /* ISTGT_USE_KQUEUE */
 2547: 			char tmp[RELOAD_CMD_LENGTH];
 2548: 			//int pgp_idx;
 2549: 			int rc2;
 2550: 
 2551: 			rc = read(istgt->sig_pipe[0], tmp, RELOAD_CMD_LENGTH);
 2552: 			if (rc < 0 || rc == 0 || rc != RELOAD_CMD_LENGTH) {
 2553: 				ISTGT_ERRLOG("read() failed\n");
 2554: 				break;
 2555: 			}
 2556: 			//pgp_idx = (int)DGET32(&tmp[1]);
 2557: 
 2558: 			if (tmp[0] == 'E') {
 2559: 				ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
 2560: 				    "exit request (main loop)\n");
 2561: 				break;
 2562: 			}
 2563: 			if (tmp[0] == 'D') {
 2564: 				rc = istgt_pg_delete(istgt);
 2565: 				MTX_LOCK(&istgt->reload_mutex);
 2566: 				istgt->pg_reload = rc < 0 ? -1 : 1;
 2567: 				rc2 = pthread_cond_broadcast(&istgt->reload_cond);
 2568: 				if (rc2 != 0) {
 2569: 					ISTGT_ERRLOG("cond_broadcast() failed\n");
 2570: 				}
 2571: 				MTX_UNLOCK(&istgt->reload_mutex);
 2572: 				if (rc < 0) {
 2573: 					ISTGT_ERRLOG("pg_delete() failed\n");
 2574: 					//break;
 2575: 				}
 2576: 			}
 2577: 			if (tmp[0] == 'U') {
 2578: 				rc = istgt_pg_update(istgt);
 2579: 				MTX_LOCK(&istgt->reload_mutex);
 2580: 				istgt->pg_reload = rc < 0 ? -1 : 1;
 2581: 				rc2 = pthread_cond_broadcast(&istgt->reload_cond);
 2582: 				if (rc2 != 0) {
 2583: 					ISTGT_ERRLOG("cond_broadcast() failed\n");
 2584: 				}
 2585: 				MTX_UNLOCK(&istgt->reload_mutex);
 2586: 				if (rc < 0) {
 2587: 					ISTGT_ERRLOG("pg_update() failed\n");
 2588: 					//break;
 2589: 				}
 2590: 			}
 2591: #ifdef ISTGT_USE_KQUEUE
 2592: 			close(kq);
 2593: #endif /* ISTGT_USE_KQUEUE */
 2594: 			ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "reload accept loop\n");
 2595: 			goto reload;
 2596: 		}
 2597: 	}
 2598: #ifdef ISTGT_USE_KQUEUE
 2599: 	close(kq);
 2600: #endif /* ISTGT_USE_KQUEUE */
 2601: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop ended\n");
 2602: 	istgt_set_state(istgt, ISTGT_STATE_EXITING);
 2603: 	istgt_lu_set_all_state(istgt, ISTGT_STATE_EXITING);
 2604: 
 2605: 	return 0;
 2606: }
 2607: 
 2608: static void
 2609: usage(void)
 2610: {
 2611: 	printf("istgt [options]\n");
 2612: 	printf("options:\n");
 2613: 	printf(" -c config  config file (default %s)\n", DEFAULT_CONFIG);
 2614: 	printf(" -p pidfile use specific file\n");
 2615: 	printf(" -l facility use specific syslog facility (default %s)\n",
 2616: 	    DEFAULT_LOG_FACILITY);
 2617: 	printf(" -m mode    operational mode (default %d, 0=traditional, "
 2618: 	    "1=normal, 2=experimental)\n", DEFAULT_ISTGT_SWMODE);
 2619: 	printf(" -t flag    trace flag (all, net, iscsi, scsi, lu)\n");
 2620: 	printf(" -q         quiet warnings\n");
 2621: 	printf(" -D         don't detach from tty\n");
 2622: 	printf(" -H         show this usage\n");
 2623: 	printf(" -V         show version\n");
 2624: }
 2625: 
 2626: int
 2627: main(int argc, char **argv)
 2628: {
 2629: 	ISTGT_Ptr istgt;
 2630: 	const char *config_file = DEFAULT_CONFIG;
 2631: 	const char *pidfile = NULL;
 2632: 	const char *logfacility = NULL;
 2633: 	const char *logpriority = NULL;
 2634: 	CONFIG *config;
 2635: 	pthread_t sigthread;
 2636: 	struct sigaction sigact, sigoldact_pipe, sigoldact_int, sigoldact_term;
 2637: 	struct sigaction sigoldact_hup, sigoldact_info;
 2638: 	struct sigaction sigoldact_wakeup, sigoldact_io;
 2639: 	sigset_t signew, sigold;
 2640: 	int retry = 10;
 2641: 	int detach = 1;
 2642: 	int swmode;
 2643: 	int ch;
 2644: 	int rc;
 2645: 
 2646: 	if (sizeof (ISCSI_BHS) != ISCSI_BHS_LEN) {
 2647: 		fprintf(stderr, "Internal Error\n");
 2648: 		exit(EXIT_FAILURE);
 2649: 	}
 2650: 
 2651: 	memset(&g_istgt, 0, sizeof g_istgt);
 2652: 	istgt = &g_istgt;
 2653: 	istgt->state = ISTGT_STATE_INVALID;
 2654: 	istgt->swmode = DEFAULT_ISTGT_SWMODE;
 2655: 	istgt->sig_pipe[0] = istgt->sig_pipe[1] = -1;
 2656: 	istgt->daemon = 0;
 2657: 	istgt->generation = 0;
 2658: 
 2659: 	while ((ch = getopt(argc, argv, "c:p:l:m:t:qDHV")) != -1) {
 2660: 		switch (ch) {
 2661: 		case 'c':
 2662: 			config_file = optarg;
 2663: 			break;
 2664: 		case 'p':
 2665: 			pidfile = optarg;
 2666: 			break;
 2667: 		case 'l':
 2668: 			logfacility = optarg;
 2669: 			break;
 2670: 		case 'm':
 2671: 			swmode = strtol(optarg, NULL, 10);
 2672: 			if (swmode == ISTGT_SWMODE_TRADITIONAL
 2673: 			    || swmode == ISTGT_SWMODE_NORMAL
 2674: 			    || swmode == ISTGT_SWMODE_EXPERIMENTAL) {
 2675: 				istgt->swmode = swmode;
 2676: 			} else {
 2677: 				fprintf(stderr, "unknown mode %x\n", swmode);
 2678: 				usage();
 2679: 				exit(EXIT_FAILURE);
 2680: 			}
 2681: 			break;
 2682: 		case 't':
 2683: 			if (strcasecmp(optarg, "NET") == 0) {
 2684: 				istgt_set_trace_flag(ISTGT_TRACE_NET);
 2685: 			} else if (strcasecmp(optarg, "ISCSI") == 0) {
 2686: 				istgt_set_trace_flag(ISTGT_TRACE_ISCSI);
 2687: 			} else if (strcasecmp(optarg, "SCSI") == 0) {
 2688: 				istgt_set_trace_flag(ISTGT_TRACE_SCSI);
 2689: 			} else if (strcasecmp(optarg, "LU") == 0) {
 2690: 				istgt_set_trace_flag(ISTGT_TRACE_LU);
 2691: 			} else if (strcasecmp(optarg, "ALL") == 0) {
 2692: 				istgt_set_trace_flag(ISTGT_TRACE_ALL);
 2693: 			} else if (strcasecmp(optarg, "NONE") == 0) {
 2694: 				istgt_set_trace_flag(ISTGT_TRACE_NONE);
 2695: 			} else {
 2696: 				fprintf(stderr, "unknown flag\n");
 2697: 				usage();
 2698: 				exit(EXIT_FAILURE);
 2699: 			}
 2700: 			break;
 2701: 		case 'q':
 2702: 			g_warn_flag = 0;
 2703: 			break;
 2704: 		case 'D':
 2705: 			detach = 0;
 2706: 			break;
 2707: 		case 'V':
 2708: 			printf("istgt version %s\n", ISTGT_VERSION);
 2709: 			printf("istgt extra version %s\n", ISTGT_EXTRA_VERSION);
 2710: 			exit(EXIT_SUCCESS);
 2711: 		case 'H':
 2712: 		default:
 2713: 			usage();
 2714: 			exit(EXIT_SUCCESS);
 2715: 		}
 2716: 	}
 2717: 
 2718: 	/* read config files */
 2719: 	config = istgt_allocate_config();
 2720: 	rc = istgt_read_config(config, config_file);
 2721: 	if (rc < 0) {
 2722: 		fprintf(stderr, "config error\n");
 2723: 		exit(EXIT_FAILURE);
 2724: 	}
 2725: 	if (config->section == NULL) {
 2726: 		fprintf(stderr, "empty config\n");
 2727: 		istgt_free_config(config);
 2728: 		exit(EXIT_FAILURE);
 2729: 	}
 2730: 	istgt->config = config;
 2731: 	istgt->config_old = NULL;
 2732: 	//istgt_print_config(config);
 2733: 
 2734: 	/* open log files */
 2735: 	if (logfacility == NULL) {
 2736: 		logfacility = istgt_get_log_facility(config);
 2737: 	}
 2738: 	rc = istgt_set_log_facility(logfacility);
 2739: 	if (rc < 0) {
 2740: 		fprintf(stderr, "log facility error\n");
 2741: 		istgt_free_config(config);
 2742: 		exit(EXIT_FAILURE);
 2743: 	}
 2744: 	if (logpriority == NULL) {
 2745: 		logpriority = DEFAULT_LOG_PRIORITY;
 2746: 	}
 2747: 	rc = istgt_set_log_priority(logpriority);
 2748: 	if (rc < 0) {
 2749: 		fprintf(stderr, "log priority error\n");
 2750: 		istgt_free_config(config);
 2751: 		exit(EXIT_FAILURE);
 2752: 	}
 2753: 	istgt_open_log();
 2754: 
 2755: 	ISTGT_NOTICELOG("istgt version %s (%s)\n", ISTGT_VERSION,
 2756: 	    ISTGT_EXTRA_VERSION);
 2757: 	switch (istgt->swmode) {
 2758: 	case ISTGT_SWMODE_TRADITIONAL:
 2759: 		ISTGT_NOTICELOG("traditional mode\n");
 2760: 		break;
 2761: 	case ISTGT_SWMODE_NORMAL:
 2762: 		ISTGT_NOTICELOG("normal mode\n");
 2763: 		break;
 2764: 	case ISTGT_SWMODE_EXPERIMENTAL:
 2765: 		ISTGT_NOTICELOG("experimental mode\n");
 2766: 		break;
 2767: 	default:
 2768: 		break;
 2769: 	}
 2770: #ifdef ISTGT_USE_KQUEUE
 2771: 	ISTGT_NOTICELOG("using kqueue\n");
 2772: #else
 2773: 	ISTGT_NOTICELOG("using poll\n");
 2774: #endif /* ISTGT_USE_KQUEUE */
 2775: #ifdef USE_ATOMIC
 2776: 	ISTGT_NOTICELOG("using host atomic\n");
 2777: #elif defined (USE_GCC_ATOMIC)
 2778: 	ISTGT_NOTICELOG("using gcc atomic\n");
 2779: #else
 2780: 	ISTGT_NOTICELOG("using generic atomic\n");
 2781: #endif /* USE_ATOMIC */
 2782: 
 2783: #ifdef ISTGT_USE_CRC32C_TABLE
 2784: 	/* build crc32c table */
 2785: 	istgt_init_crc32c_table();
 2786: #endif /* ISTGT_USE_CRC32C_TABLE */
 2787: 
 2788: 	/* initialize sub modules */
 2789: 	rc = istgt_init(istgt);
 2790: 	if (rc < 0) {
 2791: 		ISTGT_ERRLOG("istgt_init() failed\n");
 2792: 	initialize_error:
 2793: 		istgt_close_log();
 2794: 		istgt_free_config(config);
 2795: 		exit(EXIT_FAILURE);
 2796: 	}
 2797: 	rc = istgt_lu_init(istgt);
 2798: 	if (rc < 0) {
 2799: 		ISTGT_ERRLOG("istgt_lu_init() failed\n");
 2800: 		goto initialize_error;
 2801: 	}
 2802: 	rc = istgt_iscsi_init(istgt);
 2803: 	if (rc < 0) {
 2804: 		ISTGT_ERRLOG("istgt_iscsi_init() failed\n");
 2805: 		goto initialize_error;
 2806: 	}
 2807: 
 2808: 	/* override by command line */
 2809: 	if (pidfile != NULL) {
 2810: 		xfree(istgt->pidfile);
 2811: 		istgt->pidfile = xstrdup(pidfile);
 2812: 	}
 2813: 
 2814: 	/* detach from tty and run background */
 2815: 	fflush(stdout);
 2816: 	if (detach) {
 2817: 		istgt->daemon = 1;
 2818: 		rc = daemon(0, 0);
 2819: 		if (rc < 0) {
 2820: 			ISTGT_ERRLOG("daemon() failed\n");
 2821: 			goto initialize_error;
 2822: 		}
 2823: 	}
 2824: 
 2825: 	/* setup signal handler thread */
 2826: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "setup signal handler\n");
 2827: 	memset(&sigact, 0, sizeof sigact);
 2828: 	memset(&sigoldact_pipe, 0, sizeof sigoldact_pipe);
 2829: 	memset(&sigoldact_int, 0, sizeof sigoldact_int);
 2830: 	memset(&sigoldact_term, 0, sizeof sigoldact_term);
 2831: 	memset(&sigoldact_hup, 0, sizeof sigoldact_hup);
 2832: 	memset(&sigoldact_info, 0, sizeof sigoldact_info);
 2833: 	memset(&sigoldact_wakeup, 0, sizeof sigoldact_wakeup);
 2834: 	memset(&sigoldact_io, 0, sizeof sigoldact_io);
 2835: 	sigact.sa_handler = SIG_IGN;
 2836: 	sigemptyset(&sigact.sa_mask);
 2837: 	rc = sigaction(SIGPIPE, &sigact, &sigoldact_pipe);
 2838: 	if (rc < 0) {
 2839: 		ISTGT_ERRLOG("sigaction(SIGPIPE) failed\n");
 2840: 		goto initialize_error;
 2841: 	}
 2842: 	sigact.sa_handler = istgt_sigint;
 2843: 	sigemptyset(&sigact.sa_mask);
 2844: 	rc = sigaction(SIGINT, &sigact, &sigoldact_int);
 2845: 	if (rc < 0) {
 2846: 		ISTGT_ERRLOG("sigaction(SIGINT) failed\n");
 2847: 		goto initialize_error;
 2848: 	}
 2849: 	sigact.sa_handler = istgt_sigterm;
 2850: 	sigemptyset(&sigact.sa_mask);
 2851: 	rc = sigaction(SIGTERM, &sigact, &sigoldact_term);
 2852: 	if (rc < 0) {
 2853: 		ISTGT_ERRLOG("sigaction(SIGTERM) failed\n");
 2854: 		goto initialize_error;
 2855: 	}
 2856: 	sigact.sa_handler = istgt_sighup;
 2857: 	sigemptyset(&sigact.sa_mask);
 2858: 	rc = sigaction(SIGHUP, &sigact, &sigoldact_hup);
 2859: 	if (rc < 0) {
 2860: 		ISTGT_ERRLOG("sigaction(SIGHUP) failed\n");
 2861: 		goto initialize_error;
 2862: 	}
 2863: #ifdef SIGINFO
 2864: 	sigact.sa_handler = istgt_siginfo;
 2865: 	sigemptyset(&sigact.sa_mask);
 2866: 	rc = sigaction(SIGINFO, &sigact, &sigoldact_info);
 2867: 	if (rc < 0) {
 2868: 		ISTGT_ERRLOG("sigaction(SIGINFO) failed\n");
 2869: 		goto initialize_error;
 2870: 	}
 2871: #endif
 2872: #ifdef ISTGT_USE_SIGRT
 2873: 	if (ISTGT_SIGWAKEUP < SIGRTMIN
 2874: 	    || ISTGT_SIGWAKEUP > SIGRTMAX) {
 2875: 		ISTGT_ERRLOG("SIGRT error\n");
 2876: 		goto initialize_error;
 2877: 	}
 2878: #endif /* ISTGT_USE_SIGRT */
 2879: 	sigact.sa_handler = istgt_sigwakeup;
 2880: 	sigemptyset(&sigact.sa_mask);
 2881: 	rc = sigaction(ISTGT_SIGWAKEUP, &sigact, &sigoldact_wakeup);
 2882: 	if (rc < 0) {
 2883: 		ISTGT_ERRLOG("sigaction(ISTGT_SIGWAKEUP) failed\n");
 2884: 		goto initialize_error;
 2885: 	}
 2886: #ifdef SIGIO
 2887: 	sigact.sa_handler = istgt_sigio;
 2888: 	sigemptyset(&sigact.sa_mask);
 2889: 	rc = sigaction(SIGIO, &sigact, &sigoldact_io);
 2890: 	if (rc < 0) {
 2891: 		ISTGT_ERRLOG("sigaction(SIGIO) failed\n");
 2892: 		goto initialize_error;
 2893: 	}
 2894: #endif
 2895: 	pthread_sigmask(SIG_SETMASK, NULL, &signew);
 2896: 	sigaddset(&signew, SIGINT);
 2897: 	sigaddset(&signew, SIGTERM);
 2898: 	sigaddset(&signew, SIGQUIT);
 2899: 	sigaddset(&signew, SIGHUP);
 2900: #ifdef SIGINFO
 2901: 	sigaddset(&signew, SIGINFO);
 2902: #endif
 2903: 	sigaddset(&signew, SIGUSR1);
 2904: 	sigaddset(&signew, SIGUSR2);
 2905: #ifdef SIGIO
 2906: 	sigaddset(&signew, SIGIO);
 2907: #endif
 2908: 	sigaddset(&signew, ISTGT_SIGWAKEUP);
 2909: 	pthread_sigmask(SIG_SETMASK, &signew, &sigold);
 2910: #ifdef ISTGT_STACKSIZE
 2911: 	rc = pthread_create(&sigthread, &istgt->attr, &istgt_sighandler,
 2912: 	    (void *) istgt);
 2913: #else
 2914: 	rc = pthread_create(&sigthread, NULL, &istgt_sighandler,
 2915: 	    (void *) istgt);
 2916: #endif
 2917: 	if (rc != 0) {
 2918: 		ISTGT_ERRLOG("pthread_create() failed\n");
 2919: 		goto initialize_error;
 2920: 	}
 2921: #if 0
 2922: 	rc = pthread_detach(sigthread);
 2923: 	if (rc != 0) {
 2924: 		ISTGT_ERRLOG("pthread_detach() failed\n");
 2925: 		goto initialize_error;
 2926: 	}
 2927: #endif
 2928: #ifdef HAVE_PTHREAD_SET_NAME_NP
 2929: 	pthread_set_name_np(sigthread, "sigthread");
 2930: 	pthread_set_name_np(pthread_self(), "mainthread");
 2931: #endif
 2932: 
 2933: 	/* create LUN threads for command queuing */
 2934: 	rc = istgt_lu_create_threads(istgt);
 2935: 	if (rc < 0) {
 2936: 		ISTGT_ERRLOG("lu_create_threads() failed\n");
 2937: 		goto initialize_error;
 2938: 	}
 2939: 	rc = istgt_lu_set_all_state(istgt, ISTGT_STATE_RUNNING);
 2940: 	if (rc < 0) {
 2941: 		ISTGT_ERRLOG("lu_set_all_state() failed\n");
 2942: 		goto initialize_error;
 2943: 	}
 2944: 
 2945: 	/* open portals */
 2946: 	rc = istgt_open_uctl_portal(istgt);
 2947: 	if (rc < 0) {
 2948: 		ISTGT_ERRLOG("istgt_open_uctl_portal() failed\n");
 2949: 		goto initialize_error;
 2950: 	}
 2951: 	rc = istgt_open_all_portals(istgt);
 2952: 	if (rc < 0) {
 2953: 		ISTGT_ERRLOG("istgt_open_all_portals() failed\n");
 2954: 		goto initialize_error;
 2955: 	}
 2956: 
 2957: 	/* write pid */
 2958: 	rc = istgt_write_pidfile(istgt);
 2959: 	if (rc < 0) {
 2960: 		ISTGT_ERRLOG("istgt_write_pid() failed\n");
 2961: 		goto initialize_error;
 2962: 	}
 2963: 
 2964: 	/* accept loop */
 2965: 	rc = istgt_acceptor(istgt);
 2966: 	if (rc < 0) {
 2967: 		ISTGT_ERRLOG("istgt_acceptor() failed\n");
 2968: 		istgt_close_all_portals(istgt);
 2969: 		istgt_close_uctl_portal(istgt);
 2970: 		istgt_iscsi_shutdown(istgt);
 2971: 		istgt_lu_shutdown(istgt);
 2972: 		istgt_shutdown(istgt);
 2973: 		istgt_close_log();
 2974: 		config = istgt->config;
 2975: 		istgt->config = NULL;
 2976: 		istgt_free_config(config);
 2977: 		exit(EXIT_FAILURE);
 2978: 	}
 2979: 
 2980: 	/* wait threads */
 2981: 	istgt_stop_conns();
 2982: 	while (retry > 0) {
 2983: 		if (istgt_get_active_conns() == 0) {
 2984: 			break;
 2985: 		}
 2986: 		sleep(1);
 2987: 		retry--;
 2988: 	}
 2989: 	ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "retry=%d\n", retry);
 2990: 
 2991: 	ISTGT_NOTICELOG("istgt version %s (%s) exiting\n", ISTGT_VERSION,
 2992: 	    ISTGT_EXTRA_VERSION);
 2993: 
 2994: 	/* stop signal thread */
 2995: 	rc = pthread_join(sigthread, NULL);
 2996: 	if (rc != 0) {
 2997: 		ISTGT_ERRLOG("pthread_join() failed\n");
 2998: 		exit (EXIT_FAILURE);
 2999: 	}
 3000: 
 3001: 	/* cleanup */
 3002: 	istgt_close_all_portals(istgt);
 3003: 	istgt_close_uctl_portal(istgt);
 3004: 	istgt_iscsi_shutdown(istgt);
 3005: 	istgt_lu_shutdown(istgt);
 3006: 	istgt_shutdown(istgt);
 3007: 	istgt_close_log();
 3008: 	config = istgt->config;
 3009: 	istgt->config = NULL;
 3010: 	istgt_free_config(config);
 3011: 	istgt->state = ISTGT_STATE_SHUTDOWN;
 3012: 
 3013: 	return 0;
 3014: }

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