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