Annotation of embedaddon/istgt/src/istgt.c, revision 1.1

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

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