Annotation of embedaddon/istgt/src/istgt.c, revision 1.1.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>