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

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

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