1 /*
2 * Copyright (C) 2008-2015 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
istgt_parse_portal(const char * portal,char ** host,char ** port)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
istgt_add_portal_group(ISTGT_Ptr istgt,CF_SECTION * sp,int * pgp_idx)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
istgt_pg_match_all(PORTAL_GROUP * pgp,CF_SECTION * sp)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
istgt_update_portal_group(ISTGT_Ptr istgt,CF_SECTION * sp,int * pgp_idx)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
istgt_build_portal_group_array(ISTGT_Ptr istgt)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
istgt_destroy_portal_group_array(ISTGT_Ptr istgt)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
istgt_open_portal_group(PORTAL_GROUP * pgp)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
istgt_open_all_portals(ISTGT_Ptr istgt)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
istgt_close_portal_group(PORTAL_GROUP * pgp)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
istgt_close_all_portals(ISTGT_Ptr istgt)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
istgt_add_initiator_group(ISTGT_Ptr istgt,CF_SECTION * sp)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
istgt_ig_match_all(INITIATOR_GROUP * igp,CF_SECTION * sp)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
istgt_update_initiator_group(ISTGT_Ptr istgt,CF_SECTION * sp)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
istgt_build_initiator_group_array(ISTGT_Ptr istgt)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
istgt_destory_initiator_group_array(ISTGT_Ptr istgt)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
istgt_build_uctl_portal(ISTGT_Ptr istgt)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
istgt_destroy_uctl_portal(ISTGT_Ptr istgt)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
istgt_open_uctl_portal(ISTGT_Ptr istgt)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
istgt_close_uctl_portal(ISTGT_Ptr istgt)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
istgt_write_pidfile(ISTGT_Ptr istgt)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
istgt_remove_pidfile(ISTGT_Ptr istgt)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 *
istgt_get_nmval(CF_SECTION * sp,const char * key,int idx1,int idx2)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 *
istgt_get_nval(CF_SECTION * sp,const char * key,int idx)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 *
istgt_get_val(CF_SECTION * sp,const char * key)1086 istgt_get_val(CF_SECTION *sp, const char *key)
1087 {
1088 return istgt_get_nval(sp, key, 0);
1089 }
1090
1091 int
istgt_get_nintval(CF_SECTION * sp,const char * key,int idx)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
istgt_get_intval(CF_SECTION * sp,const char * key)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 *
istgt_get_log_facility(CONFIG * config)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
istgt_init(ISTGT_Ptr istgt)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 /* global mutex */
1556 rc = pthread_mutex_init(&istgt->mutex, NULL);
1557 if (rc != 0) {
1558 ISTGT_ERRLOG("mutex_init() failed\n");
1559 return -1;
1560 }
1561
1562 rc = istgt_uctl_init(istgt);
1563 if (rc < 0) {
1564 ISTGT_ERRLOG("istgt_uctl_init() failed\n");
1565 return -1;
1566 }
1567 rc = istgt_build_uctl_portal(istgt);
1568 if (rc < 0) {
1569 ISTGT_ERRLOG("istgt_build_uctl_portal() failed\n");
1570 return -1;
1571 }
1572 rc = istgt_build_portal_group_array(istgt);
1573 if (rc < 0) {
1574 ISTGT_ERRLOG("istgt_build_portal_array() failed\n");
1575 return -1;
1576 }
1577 rc = istgt_build_initiator_group_array(istgt);
1578 if (rc < 0) {
1579 ISTGT_ERRLOG("build_initiator_group_array() failed\n");
1580 return -1;
1581 }
1582
1583 rc = pthread_attr_init(&istgt->attr);
1584 if (rc != 0) {
1585 ISTGT_ERRLOG("pthread_attr_init() failed\n");
1586 return -1;
1587 }
1588 rc = pthread_attr_getstacksize(&istgt->attr, &stacksize);
1589 if (rc != 0) {
1590 ISTGT_ERRLOG("pthread_attr_getstacksize() failed\n");
1591 return -1;
1592 }
1593 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "current thread stack = %zd\n", stacksize);
1594 if (stacksize < ISTGT_STACKSIZE) {
1595 stacksize = ISTGT_STACKSIZE;
1596 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "new thread stack = %zd\n", stacksize);
1597 rc = pthread_attr_setstacksize(&istgt->attr, stacksize);
1598 if (rc != 0) {
1599 ISTGT_ERRLOG("pthread_attr_setstacksize() failed\n");
1600 return -1;
1601 }
1602 }
1603
1604 rc = pthread_mutexattr_init(&istgt->mutex_attr);
1605 if (rc != 0) {
1606 ISTGT_ERRLOG("mutexattr_init() failed\n");
1607 return -1;
1608 }
1609 #ifdef HAVE_PTHREAD_MUTEX_ADAPTIVE_NP
1610 rc = pthread_mutexattr_settype(&istgt->mutex_attr, PTHREAD_MUTEX_ADAPTIVE_NP);
1611 #else
1612 rc = pthread_mutexattr_settype(&istgt->mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
1613 #endif
1614 if (rc != 0) {
1615 ISTGT_ERRLOG("mutexattr_settype() failed\n");
1616 return -1;
1617 }
1618 rc = pthread_mutex_init(&istgt->state_mutex, &istgt->mutex_attr);
1619 if (rc != 0) {
1620 ISTGT_ERRLOG("mutex_init() failed\n");
1621 return -1;
1622 }
1623 rc = pthread_mutex_init(&istgt->reload_mutex, &istgt->mutex_attr);
1624 if (rc != 0) {
1625 ISTGT_ERRLOG("mutex_init() failed\n");
1626 return -1;
1627 }
1628 rc = pthread_cond_init(&istgt->reload_cond, NULL);
1629 if (rc != 0) {
1630 ISTGT_ERRLOG("cond_init() failed\n");
1631 return -1;
1632 }
1633
1634 rc = pipe(istgt->sig_pipe);
1635 if (rc != 0) {
1636 ISTGT_ERRLOG("pipe() failed\n");
1637 istgt->sig_pipe[0] = -1;
1638 istgt->sig_pipe[1] = -1;
1639 return -1;
1640 }
1641
1642 /* XXX TODO: add initializer */
1643
1644 istgt_set_state(istgt, ISTGT_STATE_INITIALIZED);
1645
1646 return 0;
1647 }
1648
1649 static void
istgt_shutdown(ISTGT_Ptr istgt)1650 istgt_shutdown(ISTGT_Ptr istgt)
1651 {
1652 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_shutdown\n");
1653
1654 istgt_destory_initiator_group_array(istgt);
1655 istgt_destroy_portal_group_array(istgt);
1656 istgt_destroy_uctl_portal(istgt);
1657 istgt_uctl_shutdown(istgt);
1658 istgt_remove_pidfile(istgt);
1659 xfree(istgt->pidfile);
1660 xfree(istgt->authfile);
1661 #if 0
1662 xfree(istgt->mediafile);
1663 xfree(istgt->livefile);
1664 #endif
1665 xfree(istgt->mediadirectory);
1666 xfree(istgt->nodebase);
1667
1668 if (istgt->sig_pipe[0] != -1)
1669 close(istgt->sig_pipe[0]);
1670 if (istgt->sig_pipe[1] != -1)
1671 close(istgt->sig_pipe[1]);
1672
1673 (void) pthread_cond_destroy(&istgt->reload_cond);
1674 (void) pthread_mutex_destroy(&istgt->reload_mutex);
1675 (void) pthread_mutex_destroy(&istgt->state_mutex);
1676 (void) pthread_mutex_destroy(&istgt->mutex);
1677 (void) pthread_attr_destroy(&istgt->attr);
1678 }
1679
1680 static int
istgt_pg_exist_num(CONFIG * config,int num)1681 istgt_pg_exist_num(CONFIG *config, int num)
1682 {
1683 CF_SECTION *sp;
1684
1685 sp = config->section;
1686 while (sp != NULL) {
1687 if (sp->type == ST_PORTALGROUP) {
1688 if (sp->num == num) {
1689 return 1;
1690 }
1691 }
1692 sp = sp->next;
1693 }
1694 return -1;
1695 }
1696
1697 static PORTAL_GROUP *
istgt_get_tag_portal(ISTGT_Ptr istgt,int tag)1698 istgt_get_tag_portal(ISTGT_Ptr istgt, int tag)
1699 {
1700 int i;
1701
1702 if (tag == 0)
1703 return NULL;
1704 MTX_LOCK(&istgt->mutex);
1705 for (i = 0; i < istgt->nportal_group; i++) {
1706 if (istgt->portal_group[i].tag == tag) {
1707 MTX_UNLOCK(&istgt->mutex);
1708 return &istgt->portal_group[i];
1709 }
1710 }
1711 MTX_UNLOCK(&istgt->mutex);
1712 return NULL;
1713 }
1714
1715 #if 0
1716 static int
1717 istgt_get_num_of_portals(CF_SECTION *sp)
1718 {
1719 char *label, *portal;
1720 int portals;
1721 int rc;
1722 int i;
1723
1724 for (i = 0; ; i++) {
1725 label = istgt_get_nmval(sp, "Portal", i, 0);
1726 portal = istgt_get_nmval(sp, "Portal", i, 1);
1727 if (label == NULL || portal == NULL)
1728 break;
1729 rc = istgt_parse_portal(portal, NULL, NULL);
1730 if (rc < 0) {
1731 ISTGT_ERRLOG("parse portal error (%s)\n", portal);
1732 return -1;
1733 }
1734 }
1735 portals = i;
1736 if (portals > MAX_PORTAL) {
1737 ISTGT_ERRLOG("%d > MAX_PORTAL\n", portals);
1738 return -1;
1739 }
1740 return portals;
1741 }
1742 #endif
1743
1744 #define RELOAD_CMD_LENGTH 5
1745 static int
istgt_pg_reload_delete(ISTGT_Ptr istgt)1746 istgt_pg_reload_delete(ISTGT_Ptr istgt)
1747 {
1748 char tmp[RELOAD_CMD_LENGTH];
1749 int rc;
1750
1751 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_pg_reload_delete\n");
1752
1753 istgt->pg_reload = 0;
1754 /* request delete */
1755 tmp[0] = 'D';
1756 DSET32(&tmp[1], 0);
1757 rc = write(istgt->sig_pipe[1], tmp, RELOAD_CMD_LENGTH);
1758 if (rc < 0 || rc != RELOAD_CMD_LENGTH) {
1759 ISTGT_ERRLOG("write() failed\n");
1760 return -1;
1761 }
1762 /* wait for completion */
1763 MTX_LOCK(&istgt->reload_mutex);
1764 while (istgt->pg_reload == 0) {
1765 pthread_cond_wait(&istgt->reload_cond, &istgt->reload_mutex);
1766 }
1767 rc = istgt->pg_reload;
1768 MTX_UNLOCK(&istgt->reload_mutex);
1769 if (rc < 0) {
1770 if (istgt_get_state(istgt) != ISTGT_STATE_RUNNING) {
1771 ISTGT_WARNLOG("pg_reload abort\n");
1772 return -1;
1773 }
1774 }
1775 return 0;
1776 }
1777
1778 static int
istgt_pg_reload_update(ISTGT_Ptr istgt)1779 istgt_pg_reload_update(ISTGT_Ptr istgt)
1780 {
1781 char tmp[RELOAD_CMD_LENGTH];
1782 int rc;
1783
1784 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_pg_reload_update\n");
1785
1786 istgt->pg_reload = 0;
1787 /* request update */
1788 tmp[0] = 'U';
1789 DSET32(&tmp[1], 0);
1790 rc = write(istgt->sig_pipe[1], tmp, RELOAD_CMD_LENGTH);
1791 if (rc < 0 || rc != RELOAD_CMD_LENGTH) {
1792 ISTGT_ERRLOG("write() failed\n");
1793 return -1;
1794 }
1795 /* wait for completion */
1796 MTX_LOCK(&istgt->reload_mutex);
1797 while (istgt->pg_reload == 0) {
1798 pthread_cond_wait(&istgt->reload_cond, &istgt->reload_mutex);
1799 }
1800 rc = istgt->pg_reload;
1801 MTX_UNLOCK(&istgt->reload_mutex);
1802 if (rc < 0) {
1803 if (istgt_get_state(istgt) != ISTGT_STATE_RUNNING) {
1804 ISTGT_WARNLOG("pg_reload abort\n");
1805 return -1;
1806 }
1807 }
1808 return 0;
1809 }
1810
1811 static int
istgt_ig_exist_num(CONFIG * config,int num)1812 istgt_ig_exist_num(CONFIG *config, int num)
1813 {
1814 CF_SECTION *sp;
1815
1816 sp = config->section;
1817 while (sp != NULL) {
1818 if (sp->type == ST_INITIATORGROUP) {
1819 if (sp->num == num) {
1820 return 1;
1821 }
1822 }
1823 sp = sp->next;
1824 }
1825 return -1;
1826 }
1827
1828 static int
istgt_ig_reload_delete(ISTGT_Ptr istgt)1829 istgt_ig_reload_delete(ISTGT_Ptr istgt)
1830 {
1831 INITIATOR_GROUP *igp;
1832 int rc;
1833 int i, j;
1834
1835 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_ig_reload_delete\n");
1836 MTX_LOCK(&istgt->mutex);
1837 for (i = 0; i < istgt->ninitiator_group; i++) {
1838 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "IG reload idx=%d, (%d)\n",
1839 i, istgt->ninitiator_group);
1840 igp = &istgt->initiator_group[i];
1841 rc = istgt_ig_exist_num(istgt->config, igp->tag);
1842 if (rc < 0) {
1843 if (igp->ref != 0) {
1844 ISTGT_ERRLOG("delete request for referenced IG%d\n",
1845 igp->tag);
1846 } else {
1847 ISTGT_NOTICELOG("delete IG%d\n", igp->tag);
1848 /* free old IG */
1849 for (j = 0; j < istgt->initiator_group[i].ninitiators; j++) {
1850 xfree(istgt->initiator_group[i].initiators[j]);
1851 }
1852 xfree(istgt->initiator_group[i].initiators);
1853 for (j = 0; j < istgt->initiator_group[i].nnetmasks; j++) {
1854 xfree(istgt->initiator_group[i].netmasks[j]);
1855 }
1856 xfree(istgt->initiator_group[i].netmasks);
1857
1858 /* move from beyond the IG */
1859 for (j = i; j < istgt->ninitiator_group - 1; j++) {
1860 istgt->initiator_group[j].ninitiators
1861 = istgt->initiator_group[j+1].ninitiators;
1862 istgt->initiator_group[j].initiators
1863 = istgt->initiator_group[j+1].initiators;
1864 istgt->initiator_group[j].nnetmasks
1865 = istgt->initiator_group[j+1].nnetmasks;
1866 istgt->initiator_group[j].netmasks
1867 = istgt->initiator_group[j+1].netmasks;
1868 istgt->initiator_group[j].ref
1869 = istgt->initiator_group[j+1].ref;
1870 istgt->initiator_group[j].idx
1871 = istgt->initiator_group[j+1].idx;
1872 istgt->initiator_group[j].tag
1873 = istgt->initiator_group[j+1].tag;
1874 }
1875 istgt->ninitiator_group--;
1876 }
1877 }
1878 }
1879 MTX_UNLOCK(&istgt->mutex);
1880 return 0;
1881 }
1882
1883 static int
istgt_ig_reload_update(ISTGT_Ptr istgt)1884 istgt_ig_reload_update(ISTGT_Ptr istgt)
1885 {
1886 CF_SECTION *sp;
1887 int rc;
1888 int i;
1889
1890 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_ig_reload_update\n");
1891 sp = istgt->config->section;
1892 while (sp != NULL) {
1893 if (sp->type == ST_INITIATORGROUP) {
1894 if (sp->num == 0) {
1895 ISTGT_ERRLOG("Group 0 is invalid\n");
1896 goto skip_ig;
1897 }
1898 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "IG reload tag=%d\n", sp->num);
1899 #if 0
1900 rc = istgt_ig_exist_num(istgt->config_old, sp->num);
1901 #else
1902 rc = -1;
1903 MTX_LOCK(&istgt->mutex);
1904 for (i = 0; i < istgt->ninitiator_group; i++) {
1905 if (istgt->initiator_group[i].tag == sp->num) {
1906 rc = 1;
1907 break;
1908 }
1909 }
1910 MTX_UNLOCK(&istgt->mutex);
1911 #endif
1912 if (rc < 0) {
1913 rc = istgt_add_initiator_group(istgt, sp);
1914 if (rc < 0) {
1915 ISTGT_ERRLOG("add_initiator_group() failed\n");
1916 goto skip_ig;
1917 }
1918 ISTGT_NOTICELOG("add IG%d\n", sp->num);
1919 } else {
1920 rc = istgt_update_initiator_group(istgt, sp);
1921 if (rc < 0) {
1922 ISTGT_ERRLOG("update_initiator_group() failed\n");
1923 goto skip_ig;
1924 } else if (rc == 0) {
1925 // not modified
1926 } else if (rc > 0) {
1927 ISTGT_NOTICELOG("update IG%d\n", sp->num);
1928 }
1929 }
1930 }
1931 skip_ig:
1932 sp = sp->next;
1933 }
1934 return 0;
1935 }
1936
1937 static int
istgt_reload(ISTGT_Ptr istgt)1938 istgt_reload(ISTGT_Ptr istgt)
1939 {
1940 CONFIG *config_new, *config_old;
1941 char *config_file;
1942 int rc;
1943
1944 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_reload\n");
1945 /* prepare config structure */
1946 config_new = istgt_allocate_config();
1947 config_old = istgt->config;
1948 config_file = config_old->file;
1949 rc = istgt_read_config(config_new, config_file);
1950 if (rc < 0) {
1951 ISTGT_ERRLOG("config error\n");
1952 return -1;
1953 }
1954 if (config_new->section == NULL) {
1955 ISTGT_ERRLOG("empty config\n");
1956 istgt_free_config(config_new);
1957 return -1;
1958 }
1959 istgt->config = config_new;
1960 istgt->config_old = config_old;
1961 istgt->generation++;
1962
1963 /* reload sub groups */
1964 ISTGT_NOTICELOG("reload configuration #%"PRIu32"\n", istgt->generation);
1965 rc = istgt_lu_reload_delete(istgt);
1966 if (rc < 0) {
1967 ISTGT_ERRLOG("LU reload del error\n");
1968 return -1;
1969 }
1970 rc = istgt_ig_reload_delete(istgt);
1971 if (rc < 0) {
1972 ISTGT_ERRLOG("IG reload del error\n");
1973 return -1;
1974 }
1975 rc = istgt_pg_reload_delete(istgt);
1976 if (rc < 0) {
1977 ISTGT_ERRLOG("PG reload del error\n");
1978 return -1;
1979 }
1980
1981 rc = istgt_pg_reload_update(istgt);
1982 if (rc < 0) {
1983 ISTGT_ERRLOG("PG reload add error\n");
1984 return -1;
1985 }
1986 rc = istgt_ig_reload_update(istgt);
1987 if (rc < 0) {
1988 ISTGT_ERRLOG("IG reload add error\n");
1989 return -1;
1990 }
1991 rc = istgt_lu_reload_update(istgt);
1992 if (rc < 0) {
1993 ISTGT_ERRLOG("LU reload add error\n");
1994 return -1;
1995 }
1996
1997 istgt->config_old = NULL;
1998 istgt_free_config(config_old);
1999 return 0;
2000 }
2001
2002 static int
istgt_stop_loop(ISTGT_Ptr istgt)2003 istgt_stop_loop(ISTGT_Ptr istgt)
2004 {
2005 char tmp[RELOAD_CMD_LENGTH];
2006 int rc;
2007
2008 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_stop_loop\n");
2009 tmp[0] = 'E';
2010 DSET32(&tmp[1], 0);
2011 rc = write(istgt->sig_pipe[1], tmp, RELOAD_CMD_LENGTH);
2012 if (rc < 0 || rc != RELOAD_CMD_LENGTH) {
2013 ISTGT_ERRLOG("write() failed\n");
2014 /* ignore error */
2015 }
2016 return 0;
2017 }
2018
2019
2020 static void
istgt_sigint(int signo)2021 istgt_sigint(int signo __attribute__((__unused__)))
2022 {
2023 }
2024
2025 static void
istgt_sigterm(int signo)2026 istgt_sigterm(int signo __attribute__((__unused__)))
2027 {
2028 }
2029
2030 static void
istgt_sighup(int signo)2031 istgt_sighup(int signo __attribute__((__unused__)))
2032 {
2033 }
2034
2035 #ifdef SIGINFO
2036 static void
istgt_siginfo(int signo)2037 istgt_siginfo(int signo __attribute__((__unused__)))
2038 {
2039 /* nothing */
2040 }
2041 #endif
2042
2043 static void
istgt_sigwakeup(int signo)2044 istgt_sigwakeup(int signo __attribute__((__unused__)))
2045 {
2046 }
2047
2048 #ifdef SIGIO
2049 static void
istgt_sigio(int signo)2050 istgt_sigio(int signo __attribute__((__unused__)))
2051 {
2052 }
2053 #endif
2054
2055 static void *
istgt_sighandler(void * arg)2056 istgt_sighandler(void *arg)
2057 {
2058 ISTGT_Ptr istgt = (ISTGT_Ptr) arg;
2059 sigset_t signew;
2060 int signo;
2061
2062 sigemptyset(&signew);
2063 sigaddset(&signew, SIGINT);
2064 sigaddset(&signew, SIGTERM);
2065 sigaddset(&signew, SIGQUIT);
2066 sigaddset(&signew, SIGHUP);
2067 #ifdef SIGINFO
2068 sigaddset(&signew, SIGINFO);
2069 #endif
2070 sigaddset(&signew, SIGUSR1);
2071 sigaddset(&signew, SIGUSR2);
2072 #ifdef SIGIO
2073 sigaddset(&signew, SIGIO);
2074 #endif
2075
2076 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop start\n");
2077 while (1) {
2078 if (istgt_get_state(istgt) == ISTGT_STATE_EXITING
2079 || istgt_get_state(istgt) == ISTGT_STATE_SHUTDOWN) {
2080 break;
2081 }
2082 sigwait(&signew, &signo);
2083 switch (signo) {
2084 case SIGINT:
2085 printf("SIGINT catch\n");
2086 istgt_stop_loop(istgt);
2087 istgt_set_state(istgt, ISTGT_STATE_EXITING);
2088 istgt_lu_set_all_state(istgt, ISTGT_STATE_EXITING);
2089 break;
2090 case SIGTERM:
2091 printf("SIGTERM catch\n");
2092 istgt_stop_loop(istgt);
2093 istgt_set_state(istgt, ISTGT_STATE_EXITING);
2094 istgt_lu_set_all_state(istgt, ISTGT_STATE_EXITING);
2095 break;
2096 case SIGQUIT:
2097 printf("SIGQUIT catch\n");
2098 exit(EXIT_SUCCESS);
2099 break;
2100 case SIGHUP:
2101 printf("SIGHUP catch\n");
2102 istgt_reload(istgt);
2103 break;
2104 #ifdef SIGINFO
2105 case SIGINFO:
2106 printf("SIGINFO catch\n");
2107 istgt_set_trace_flag(ISTGT_TRACE_ISCSI);
2108 break;
2109 #endif
2110 case SIGUSR1:
2111 printf("SIGUSR1 catch\n");
2112 istgt_set_trace_flag(ISTGT_TRACE_NONE);
2113 break;
2114 case SIGUSR2:
2115 printf("SIGUSR2 catch\n");
2116 //istgt_set_trace_flag(ISTGT_TRACE_SCSI);
2117 istgt_set_trace_flag(ISTGT_TRACE_ALL);
2118 break;
2119 #ifdef SIGIO
2120 case SIGIO:
2121 //printf("SIGIO catch\n");
2122 break;
2123 #endif
2124 default:
2125 break;
2126 }
2127 }
2128 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop ended\n");
2129
2130 return NULL;
2131 }
2132
2133 static PORTAL *
istgt_get_sock_portal(ISTGT_Ptr istgt,int sock)2134 istgt_get_sock_portal(ISTGT_Ptr istgt, int sock)
2135 {
2136 int i, j;
2137
2138 if (sock < 0)
2139 return NULL;
2140 MTX_LOCK(&istgt->mutex);
2141 for (i = 0; i < istgt->nportal_group; i++) {
2142 for (j = 0; j < istgt->portal_group[i].nportals; j++) {
2143 if (istgt->portal_group[i].portals[j]->sock == sock) {
2144 MTX_UNLOCK(&istgt->mutex);
2145 return istgt->portal_group[i].portals[j];
2146 }
2147 }
2148 }
2149 MTX_UNLOCK(&istgt->mutex);
2150 return NULL;
2151 }
2152
2153 static int
istgt_pg_delete(ISTGT_Ptr istgt)2154 istgt_pg_delete(ISTGT_Ptr istgt)
2155 {
2156 PORTAL_GROUP *pgp;
2157 int rc;
2158 int i;
2159
2160 MTX_LOCK(&istgt->mutex);
2161 for (i = 0; i < istgt->nportal_group; i++) {
2162 pgp = &istgt->portal_group[i];
2163 if (pgp->tag == 0)
2164 continue;
2165 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "PG reload idx=%d, tag=%d, (%d)\n",
2166 i, pgp->tag, istgt->nportal_group);
2167 rc = istgt_pg_exist_num(istgt->config, pgp->tag);
2168 if (rc < 0) {
2169 if (pgp->ref != 0) {
2170 ISTGT_ERRLOG("delete request for referenced PG%d\n",
2171 pgp->tag);
2172 } else {
2173 ISTGT_NOTICELOG("delete PG%d\n", pgp->tag);
2174 pgp->tag = 0;
2175 (void) istgt_close_portal_group(pgp);
2176 }
2177 }
2178 }
2179 MTX_UNLOCK(&istgt->mutex);
2180 return 0;
2181 }
2182
2183 static int
istgt_pg_update(ISTGT_Ptr istgt)2184 istgt_pg_update(ISTGT_Ptr istgt)
2185 {
2186 PORTAL_GROUP *pgp;
2187 CF_SECTION *sp;
2188 int pgp_idx;
2189 int rc;
2190 int i;
2191
2192 sp = istgt->config->section;
2193 while (sp != NULL) {
2194 if (sp->type == ST_PORTALGROUP) {
2195 if (sp->num == 0) {
2196 ISTGT_ERRLOG("Group 0 is invalid\n");
2197 goto skip_pg;
2198 }
2199 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "PG reload tag=%d\n", sp->num);
2200 #if 0
2201 rc = istgt_pg_exist_num(istgt->config_old, sp->num);
2202 #else
2203 rc = -1;
2204 MTX_LOCK(&istgt->mutex);
2205 for (i = 0; i < istgt->nportal_group; i++) {
2206 if (istgt->portal_group[i].tag == sp->num) {
2207 rc = 1;
2208 break;
2209 }
2210 }
2211 MTX_UNLOCK(&istgt->mutex);
2212 #endif
2213 if (rc < 0) {
2214 rc = istgt_add_portal_group(istgt, sp, &pgp_idx);
2215 if (rc < 0) {
2216 ISTGT_ERRLOG("add_portal_group() failed\n");
2217 goto skip_pg;
2218 }
2219 MTX_LOCK(&istgt->mutex);
2220 pgp = &istgt->portal_group[pgp_idx];
2221 (void) istgt_open_portal_group(pgp);
2222 MTX_UNLOCK(&istgt->mutex);
2223 ISTGT_NOTICELOG("add PG%d\n", sp->num);
2224 } else {
2225 //portals = istgt_get_num_of_portals(sp);
2226 pgp = istgt_get_tag_portal(istgt, sp->num);
2227 if (istgt_pg_match_all(pgp, sp)) {
2228 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
2229 "skip for PG%d\n", sp->num);
2230 } else if (pgp->ref != 0) {
2231 ISTGT_ERRLOG("update request for referenced PG%d\n",
2232 pgp->tag);
2233 } else {
2234 /* delete old sock */
2235 MTX_LOCK(&istgt->mutex);
2236 pgp_idx = pgp->idx;
2237 (void) istgt_close_portal_group(pgp);
2238 MTX_UNLOCK(&istgt->mutex);
2239 rc = istgt_update_portal_group(istgt, sp, &pgp_idx);
2240 if (rc < 0) {
2241 ISTGT_ERRLOG("update_portal_group() failed\n");
2242 goto skip_pg;
2243 } else if (rc == 0) {
2244 // not modified
2245 } else if (rc > 0) {
2246 /* add new sock */
2247 MTX_LOCK(&istgt->mutex);
2248 pgp = &istgt->portal_group[pgp_idx];
2249 (void) istgt_open_portal_group(pgp);
2250 MTX_UNLOCK(&istgt->mutex);
2251 ISTGT_NOTICELOG("update PG%d\n", sp->num);
2252 }
2253 }
2254 }
2255 }
2256 skip_pg:
2257 sp = sp->next;
2258 }
2259 return 0;
2260 }
2261
2262 static int
istgt_acceptor(ISTGT_Ptr istgt)2263 istgt_acceptor(ISTGT_Ptr istgt)
2264 {
2265 PORTAL *pp;
2266 #ifdef ISTGT_USE_KQUEUE
2267 int kq;
2268 struct kevent kev;
2269 struct timespec kev_timeout;
2270 int kqsocks[MAX_PORTAL_GROUP + MAX_UCPORTAL];
2271 #else
2272 struct pollfd fds[MAX_PORTAL_GROUP + MAX_UCPORTAL];
2273 #endif /* ISTGT_USE_KQUEUE */
2274 struct sockaddr_storage sa;
2275 socklen_t salen;
2276 int sock;
2277 int rc, n;
2278 int ucidx;
2279 int nidx;
2280 int i, j;
2281
2282 if (istgt_get_state(istgt) != ISTGT_STATE_INITIALIZED) {
2283 ISTGT_ERRLOG("not initialized\n");
2284 return -1;
2285 }
2286 /* now running main thread */
2287 istgt_set_state(istgt, ISTGT_STATE_RUNNING);
2288
2289 reload:
2290 nidx = 0;
2291 #ifdef ISTGT_USE_KQUEUE
2292 kq = kqueue();
2293 if (kq == -1) {
2294 ISTGT_ERRLOG("kqueue() failed\n");
2295 return -1;
2296 }
2297 for (i = 0; i < (int)(sizeof kqsocks / sizeof *kqsocks); i++) {
2298 kqsocks[i] = -1;
2299 }
2300 MTX_LOCK(&istgt->mutex);
2301 for (i = 0; i < istgt->nportal_group; i++) {
2302 for (j = 0; j < istgt->portal_group[i].nportals; j++) {
2303 if (istgt->portal_group[i].portals[j]->sock >= 0) {
2304 ISTGT_EV_SET(&kev, istgt->portal_group[i].portals[j]->sock,
2305 EVFILT_READ, EV_ADD, 0, 0, NULL);
2306 rc = kevent(kq, &kev, 1, NULL, 0, NULL);
2307 if (rc == -1) {
2308 MTX_UNLOCK(&istgt->mutex);
2309 ISTGT_ERRLOG("kevent() failed\n");
2310 close(kq);
2311 return -1;
2312 }
2313 kqsocks[nidx] = istgt->portal_group[i].portals[j]->sock;
2314 nidx++;
2315 }
2316 }
2317 }
2318 MTX_UNLOCK(&istgt->mutex);
2319 ucidx = nidx;
2320 for (i = 0; i < istgt->nuctl_portal; i++) {
2321 ISTGT_EV_SET(&kev, istgt->uctl_portal[i].sock,
2322 EVFILT_READ, EV_ADD, 0, 0, NULL);
2323 rc = kevent(kq, &kev, 1, NULL, 0, NULL);
2324 if (rc == -1) {
2325 ISTGT_ERRLOG("kevent() failed\n");
2326 close(kq);
2327 return -1;
2328 }
2329 kqsocks[nidx] = istgt->uctl_portal[i].sock;
2330 nidx++;
2331 }
2332 ISTGT_EV_SET(&kev, istgt->sig_pipe[0], EVFILT_READ, EV_ADD, 0, 0, NULL);
2333 rc = kevent(kq, &kev, 1, NULL, 0, NULL);
2334 if (rc == -1) {
2335 ISTGT_ERRLOG("kevent() failed\n");
2336 close(kq);
2337 return -1;
2338 }
2339 kqsocks[nidx] = istgt->sig_pipe[0];
2340 nidx++;
2341
2342 if (!istgt->daemon) {
2343 ISTGT_EV_SET(&kev, SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
2344 rc = kevent(kq, &kev, 1, NULL, 0, NULL);
2345 if (rc == -1) {
2346 ISTGT_ERRLOG("kevent() failed\n");
2347 close(kq);
2348 return -1;
2349 }
2350 ISTGT_EV_SET(&kev, SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
2351 rc = kevent(kq, &kev, 1, NULL, 0, NULL);
2352 if (rc == -1) {
2353 ISTGT_ERRLOG("kevent() failed\n");
2354 close(kq);
2355 return -1;
2356 }
2357 }
2358 #else
2359 memset(&fds, 0, sizeof fds);
2360 MTX_LOCK(&istgt->mutex);
2361 for (i = 0; i < istgt->nportal_group; i++) {
2362 for (j = 0; j < istgt->portal_group[i].nportals; j++) {
2363 if (istgt->portal_group[i].portals[j]->sock >= 0) {
2364 fds[i].fd = istgt->portal_group[i].portals[j]->sock;
2365 fds[i].events = POLLIN;
2366 nidx++;
2367 }
2368 }
2369 }
2370 MTX_UNLOCK(&istgt->mutex);
2371 ucidx = nidx;
2372 for (i = 0; i < istgt->nuctl_portal; i++) {
2373 fds[ucidx + i].fd = istgt->uctl_portal[i].sock;
2374 fds[ucidx + i].events = POLLIN;
2375 nidx++;
2376 }
2377 fds[nidx].fd = istgt->sig_pipe[0];
2378 fds[nidx].events = POLLIN;
2379 nidx++;
2380 #endif /* ISTGT_USE_KQUEUE */
2381
2382 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop start\n");
2383 while (1) {
2384 if (istgt_get_state(istgt) != ISTGT_STATE_RUNNING) {
2385 break;
2386 }
2387 #ifdef ISTGT_USE_KQUEUE
2388 //ISTGT_TRACELOG(ISTGT_TRACE_NET, "kevent %d\n", nidx);
2389 kev_timeout.tv_sec = 10;
2390 kev_timeout.tv_nsec = 0;
2391 rc = kevent(kq, NULL, 0, &kev, 1, &kev_timeout);
2392 if (rc == -1 && errno == EINTR) {
2393 continue;
2394 }
2395 if (rc == -1) {
2396 ISTGT_ERRLOG("kevent() failed\n");
2397 break;
2398 }
2399 if (rc == 0) {
2400 /* idle timeout */
2401 //ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "kevent TIMEOUT\n");
2402 continue;
2403 }
2404 if (kev.filter == EVFILT_SIGNAL) {
2405 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "kevent SIGNAL\n");
2406 if (kev.ident == SIGINT || kev.ident == SIGTERM) {
2407 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
2408 "kevent SIGNAL SIGINT/SIGTERM\n");
2409 break;
2410 }
2411 continue;
2412 }
2413 #else
2414 //ISTGT_TRACELOG(ISTGT_TRACE_NET, "poll %d\n", nidx);
2415 rc = poll(fds, nidx, POLLWAIT);
2416 if (rc == -1 && errno == EINTR) {
2417 continue;
2418 }
2419 if (rc == -1) {
2420 ISTGT_ERRLOG("poll() failed\n");
2421 break;
2422 }
2423 if (rc == 0) {
2424 /* no fds */
2425 //ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "poll TIMEOUT\n");
2426 continue;
2427 }
2428 #endif /* ISTGT_USE_KQUEUE */
2429
2430 n = rc;
2431 for (i = 0; n != 0 && i < ucidx; i++) {
2432 #ifdef ISTGT_USE_KQUEUE
2433 if (kev.ident == (uintptr_t)kqsocks[i]) {
2434 if (kev.flags) {
2435 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
2436 "flags %x\n",
2437 kev.flags);
2438 }
2439 #else
2440 if (fds[i].revents) {
2441 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
2442 "events %x\n",
2443 fds[i].revents);
2444 }
2445 if (fds[i].revents & POLLIN) {
2446 #endif /* ISTGT_USE_KQUEUE */
2447 n--;
2448 memset(&sa, 0, sizeof(sa));
2449 salen = sizeof(sa);
2450 #ifdef ISTGT_USE_KQUEUE
2451 ISTGT_TRACELOG(ISTGT_TRACE_NET, "accept %ld\n",
2452 (unsigned long)kev.ident);
2453 pp = istgt_get_sock_portal(istgt, kev.ident);
2454 rc = accept(kev.ident, (struct sockaddr *) &sa, &salen);
2455 #else
2456 ISTGT_TRACELOG(ISTGT_TRACE_NET, "accept %d\n",
2457 fds[i].fd);
2458 pp = istgt_get_sock_portal(istgt, fds[i].fd);
2459 rc = accept(fds[i].fd, (struct sockaddr *) &sa, &salen);
2460 #endif /* ISTGT_USE_KQUEUE */
2461 if (rc < 0) {
2462 if (errno == ECONNABORTED || errno == ECONNRESET) {
2463 continue;
2464 }
2465 ISTGT_ERRLOG("accept error: %d(errno=%d)\n",
2466 rc, errno);
2467 continue;
2468 }
2469 sock = rc;
2470 #if 0
2471 rc = fcntl(sock, F_GETFL, 0);
2472 if (rc == -1) {
2473 ISTGT_ERRLOG("fcntl() failed\n");
2474 continue;
2475 }
2476 rc = fcntl(sock, F_SETFL, (rc | O_NONBLOCK));
2477 if (rc == -1) {
2478 ISTGT_ERRLOG("fcntl() failed\n");
2479 continue;
2480 }
2481 #endif
2482 rc = istgt_create_conn(istgt, pp, sock,
2483 (struct sockaddr *) &sa, salen);
2484 if (rc < 0) {
2485 close(sock);
2486 ISTGT_ERRLOG("istgt_create_conn() failed\n");
2487 continue;
2488 }
2489 }
2490 }
2491
2492 /* check for control */
2493 for (i = 0; n != 0 && i < istgt->nuctl_portal; i++) {
2494 #ifdef ISTGT_USE_KQUEUE
2495 if (kev.ident == (uintptr_t)istgt->uctl_portal[i].sock) {
2496 if (kev.flags) {
2497 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
2498 "flags %x\n",
2499 kev.flags);
2500 }
2501 #else
2502 if (fds[ucidx + i].revents) {
2503 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
2504 "events %x\n",
2505 fds[ucidx + i].revents);
2506 }
2507 if (fds[ucidx + i].revents & POLLIN) {
2508 #endif /* ISTGT_USE_KQUEUE */
2509 n--;
2510 memset(&sa, 0, sizeof(sa));
2511 salen = sizeof(sa);
2512 #ifdef ISTGT_USE_KQUEUE
2513 ISTGT_TRACELOG(ISTGT_TRACE_NET,
2514 "accept %ld\n", (unsigned long)kev.ident);
2515 rc = accept(kev.ident,
2516 (struct sockaddr *) &sa, &salen);
2517 #else
2518 ISTGT_TRACELOG(ISTGT_TRACE_NET,
2519 "accept %d\n", fds[ucidx + i].fd);
2520 rc = accept(fds[ucidx + i].fd,
2521 (struct sockaddr *) &sa, &salen);
2522 #endif /* ISTGT_USE_KQUEUE */
2523 if (rc < 0) {
2524 ISTGT_ERRLOG("accept error: %d\n", rc);
2525 continue;
2526 }
2527 sock = rc;
2528 rc = istgt_create_uctl(istgt,
2529 &istgt->uctl_portal[i], sock,
2530 (struct sockaddr *) &sa, salen);
2531 if (rc < 0) {
2532 close(sock);
2533 ISTGT_ERRLOG("istgt_create_uctl() failed\n");
2534 continue;
2535 }
2536 }
2537 }
2538
2539 /* check for signal thread */
2540 #ifdef ISTGT_USE_KQUEUE
2541 if (kev.ident == (uintptr_t)istgt->sig_pipe[0]) {
2542 if (kev.flags & (EV_EOF|EV_ERROR)) {
2543 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
2544 "kevent EOF/ERROR\n");
2545 break;
2546 }
2547 #else
2548 if (fds[nidx - 1].revents & POLLHUP) {
2549 break;
2550 }
2551 if (fds[nidx - 1].revents & POLLIN) {
2552 #endif /* ISTGT_USE_KQUEUE */
2553 char tmp[RELOAD_CMD_LENGTH];
2554 //int pgp_idx;
2555 int rc2;
2556
2557 rc = read(istgt->sig_pipe[0], tmp, RELOAD_CMD_LENGTH);
2558 if (rc < 0 || rc == 0 || rc != RELOAD_CMD_LENGTH) {
2559 ISTGT_ERRLOG("read() failed\n");
2560 break;
2561 }
2562 //pgp_idx = (int)DGET32(&tmp[1]);
2563
2564 if (tmp[0] == 'E') {
2565 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
2566 "exit request (main loop)\n");
2567 break;
2568 }
2569 if (tmp[0] == 'D') {
2570 rc = istgt_pg_delete(istgt);
2571 MTX_LOCK(&istgt->reload_mutex);
2572 istgt->pg_reload = rc < 0 ? -1 : 1;
2573 rc2 = pthread_cond_broadcast(&istgt->reload_cond);
2574 if (rc2 != 0) {
2575 ISTGT_ERRLOG("cond_broadcast() failed\n");
2576 }
2577 MTX_UNLOCK(&istgt->reload_mutex);
2578 if (rc < 0) {
2579 ISTGT_ERRLOG("pg_delete() failed\n");
2580 //break;
2581 }
2582 }
2583 if (tmp[0] == 'U') {
2584 rc = istgt_pg_update(istgt);
2585 MTX_LOCK(&istgt->reload_mutex);
2586 istgt->pg_reload = rc < 0 ? -1 : 1;
2587 rc2 = pthread_cond_broadcast(&istgt->reload_cond);
2588 if (rc2 != 0) {
2589 ISTGT_ERRLOG("cond_broadcast() failed\n");
2590 }
2591 MTX_UNLOCK(&istgt->reload_mutex);
2592 if (rc < 0) {
2593 ISTGT_ERRLOG("pg_update() failed\n");
2594 //break;
2595 }
2596 }
2597 #ifdef ISTGT_USE_KQUEUE
2598 close(kq);
2599 #endif /* ISTGT_USE_KQUEUE */
2600 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "reload accept loop\n");
2601 goto reload;
2602 }
2603 }
2604 #ifdef ISTGT_USE_KQUEUE
2605 close(kq);
2606 #endif /* ISTGT_USE_KQUEUE */
2607 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop ended\n");
2608 istgt_set_state(istgt, ISTGT_STATE_EXITING);
2609 istgt_lu_set_all_state(istgt, ISTGT_STATE_EXITING);
2610
2611 return 0;
2612 }
2613
2614 static void
2615 usage(void)
2616 {
2617 printf("istgt [options]\n");
2618 printf("options:\n");
2619 printf(" -c config config file (default %s)\n", DEFAULT_CONFIG);
2620 printf(" -p pidfile use specific file\n");
2621 printf(" -l facility use specific syslog facility (default %s)\n",
2622 DEFAULT_LOG_FACILITY);
2623 printf(" -m mode operational mode (default %d, 0=traditional, "
2624 "1=normal, 2=experimental)\n", DEFAULT_ISTGT_SWMODE);
2625 printf(" -t flag trace flag (all, net, iscsi, scsi, lu)\n");
2626 printf(" -q quiet warnings\n");
2627 printf(" -D don't detach from tty\n");
2628 printf(" -H show this usage\n");
2629 printf(" -V show version\n");
2630 }
2631
2632 int
2633 main(int argc, char **argv)
2634 {
2635 ISTGT_Ptr istgt;
2636 const char *config_file = DEFAULT_CONFIG;
2637 const char *pidfile = NULL;
2638 const char *logfacility = NULL;
2639 const char *logpriority = NULL;
2640 CONFIG *config;
2641 pthread_t sigthread;
2642 struct sigaction sigact, sigoldact_pipe, sigoldact_int, sigoldact_term;
2643 struct sigaction sigoldact_hup, sigoldact_info;
2644 struct sigaction sigoldact_wakeup, sigoldact_io;
2645 sigset_t signew, sigold;
2646 int retry = 10;
2647 int detach = 1;
2648 int swmode;
2649 int ch;
2650 int rc;
2651
2652 if (sizeof (ISCSI_BHS) != ISCSI_BHS_LEN) {
2653 fprintf(stderr, "Internal Error\n");
2654 exit(EXIT_FAILURE);
2655 }
2656
2657 memset(&g_istgt, 0, sizeof g_istgt);
2658 istgt = &g_istgt;
2659 istgt->state = ISTGT_STATE_INVALID;
2660 istgt->swmode = DEFAULT_ISTGT_SWMODE;
2661 istgt->sig_pipe[0] = istgt->sig_pipe[1] = -1;
2662 istgt->daemon = 0;
2663 istgt->generation = 0;
2664
2665 while ((ch = getopt(argc, argv, "c:p:l:m:t:qDHV")) != -1) {
2666 switch (ch) {
2667 case 'c':
2668 config_file = optarg;
2669 break;
2670 case 'p':
2671 pidfile = optarg;
2672 break;
2673 case 'l':
2674 logfacility = optarg;
2675 break;
2676 case 'm':
2677 swmode = strtol(optarg, NULL, 10);
2678 if (swmode == ISTGT_SWMODE_TRADITIONAL
2679 || swmode == ISTGT_SWMODE_NORMAL
2680 || swmode == ISTGT_SWMODE_EXPERIMENTAL) {
2681 istgt->swmode = swmode;
2682 } else {
2683 fprintf(stderr, "unknown mode %x\n", swmode);
2684 usage();
2685 exit(EXIT_FAILURE);
2686 }
2687 break;
2688 case 't':
2689 if (strcasecmp(optarg, "NET") == 0) {
2690 istgt_set_trace_flag(ISTGT_TRACE_NET);
2691 } else if (strcasecmp(optarg, "ISCSI") == 0) {
2692 istgt_set_trace_flag(ISTGT_TRACE_ISCSI);
2693 } else if (strcasecmp(optarg, "SCSI") == 0) {
2694 istgt_set_trace_flag(ISTGT_TRACE_SCSI);
2695 } else if (strcasecmp(optarg, "LU") == 0) {
2696 istgt_set_trace_flag(ISTGT_TRACE_LU);
2697 } else if (strcasecmp(optarg, "ALL") == 0) {
2698 istgt_set_trace_flag(ISTGT_TRACE_ALL);
2699 } else if (strcasecmp(optarg, "NONE") == 0) {
2700 istgt_set_trace_flag(ISTGT_TRACE_NONE);
2701 } else {
2702 fprintf(stderr, "unknown flag\n");
2703 usage();
2704 exit(EXIT_FAILURE);
2705 }
2706 break;
2707 case 'q':
2708 g_warn_flag = 0;
2709 break;
2710 case 'D':
2711 detach = 0;
2712 break;
2713 case 'V':
2714 printf("istgt version %s\n", ISTGT_VERSION);
2715 printf("istgt extra version %s\n", ISTGT_EXTRA_VERSION);
2716 exit(EXIT_SUCCESS);
2717 case 'H':
2718 default:
2719 usage();
2720 exit(EXIT_SUCCESS);
2721 }
2722 }
2723
2724 /* read config files */
2725 config = istgt_allocate_config();
2726 rc = istgt_read_config(config, config_file);
2727 if (rc < 0) {
2728 fprintf(stderr, "config error\n");
2729 exit(EXIT_FAILURE);
2730 }
2731 if (config->section == NULL) {
2732 fprintf(stderr, "empty config\n");
2733 istgt_free_config(config);
2734 exit(EXIT_FAILURE);
2735 }
2736 istgt->config = config;
2737 istgt->config_old = NULL;
2738 //istgt_print_config(config);
2739
2740 /* open log files */
2741 if (logfacility == NULL) {
2742 logfacility = istgt_get_log_facility(config);
2743 }
2744 rc = istgt_set_log_facility(logfacility);
2745 if (rc < 0) {
2746 fprintf(stderr, "log facility error\n");
2747 istgt_free_config(config);
2748 exit(EXIT_FAILURE);
2749 }
2750 if (logpriority == NULL) {
2751 logpriority = DEFAULT_LOG_PRIORITY;
2752 }
2753 rc = istgt_set_log_priority(logpriority);
2754 if (rc < 0) {
2755 fprintf(stderr, "log priority error\n");
2756 istgt_free_config(config);
2757 exit(EXIT_FAILURE);
2758 }
2759 istgt_open_log();
2760
2761 ISTGT_NOTICELOG("istgt version %s (%s)\n", ISTGT_VERSION,
2762 ISTGT_EXTRA_VERSION);
2763 switch (istgt->swmode) {
2764 case ISTGT_SWMODE_TRADITIONAL:
2765 ISTGT_NOTICELOG("traditional mode\n");
2766 break;
2767 case ISTGT_SWMODE_NORMAL:
2768 ISTGT_NOTICELOG("normal mode\n");
2769 break;
2770 case ISTGT_SWMODE_EXPERIMENTAL:
2771 ISTGT_NOTICELOG("experimental mode\n");
2772 break;
2773 default:
2774 break;
2775 }
2776 #ifdef ISTGT_USE_KQUEUE
2777 ISTGT_NOTICELOG("using kqueue\n");
2778 #else
2779 ISTGT_NOTICELOG("using poll\n");
2780 #endif /* ISTGT_USE_KQUEUE */
2781 #ifdef USE_ATOMIC
2782 ISTGT_NOTICELOG("using host atomic\n");
2783 #elif defined (USE_GCC_ATOMIC)
2784 ISTGT_NOTICELOG("using gcc atomic\n");
2785 #else
2786 ISTGT_NOTICELOG("using generic atomic\n");
2787 #endif /* USE_ATOMIC */
2788
2789 #ifdef ISTGT_USE_CRC32C_TABLE
2790 /* build crc32c table */
2791 istgt_init_crc32c_table();
2792 #endif /* ISTGT_USE_CRC32C_TABLE */
2793
2794 /* initialize sub modules */
2795 rc = istgt_init(istgt);
2796 if (rc < 0) {
2797 ISTGT_ERRLOG("istgt_init() failed\n");
2798 initialize_error:
2799 istgt_close_log();
2800 istgt_free_config(config);
2801 exit(EXIT_FAILURE);
2802 }
2803 rc = istgt_lu_init(istgt);
2804 if (rc < 0) {
2805 ISTGT_ERRLOG("istgt_lu_init() failed\n");
2806 goto initialize_error;
2807 }
2808 rc = istgt_iscsi_init(istgt);
2809 if (rc < 0) {
2810 ISTGT_ERRLOG("istgt_iscsi_init() failed\n");
2811 goto initialize_error;
2812 }
2813
2814 /* override by command line */
2815 if (pidfile != NULL) {
2816 xfree(istgt->pidfile);
2817 istgt->pidfile = xstrdup(pidfile);
2818 }
2819
2820 /* detach from tty and run background */
2821 fflush(stdout);
2822 if (detach) {
2823 istgt->daemon = 1;
2824 rc = daemon(0, 0);
2825 if (rc < 0) {
2826 ISTGT_ERRLOG("daemon() failed\n");
2827 goto initialize_error;
2828 }
2829 }
2830
2831 /* setup signal handler thread */
2832 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "setup signal handler\n");
2833 memset(&sigact, 0, sizeof sigact);
2834 memset(&sigoldact_pipe, 0, sizeof sigoldact_pipe);
2835 memset(&sigoldact_int, 0, sizeof sigoldact_int);
2836 memset(&sigoldact_term, 0, sizeof sigoldact_term);
2837 memset(&sigoldact_hup, 0, sizeof sigoldact_hup);
2838 memset(&sigoldact_info, 0, sizeof sigoldact_info);
2839 memset(&sigoldact_wakeup, 0, sizeof sigoldact_wakeup);
2840 memset(&sigoldact_io, 0, sizeof sigoldact_io);
2841 sigact.sa_handler = SIG_IGN;
2842 sigemptyset(&sigact.sa_mask);
2843 rc = sigaction(SIGPIPE, &sigact, &sigoldact_pipe);
2844 if (rc < 0) {
2845 ISTGT_ERRLOG("sigaction(SIGPIPE) failed\n");
2846 goto initialize_error;
2847 }
2848 sigact.sa_handler = istgt_sigint;
2849 sigemptyset(&sigact.sa_mask);
2850 rc = sigaction(SIGINT, &sigact, &sigoldact_int);
2851 if (rc < 0) {
2852 ISTGT_ERRLOG("sigaction(SIGINT) failed\n");
2853 goto initialize_error;
2854 }
2855 sigact.sa_handler = istgt_sigterm;
2856 sigemptyset(&sigact.sa_mask);
2857 rc = sigaction(SIGTERM, &sigact, &sigoldact_term);
2858 if (rc < 0) {
2859 ISTGT_ERRLOG("sigaction(SIGTERM) failed\n");
2860 goto initialize_error;
2861 }
2862 sigact.sa_handler = istgt_sighup;
2863 sigemptyset(&sigact.sa_mask);
2864 rc = sigaction(SIGHUP, &sigact, &sigoldact_hup);
2865 if (rc < 0) {
2866 ISTGT_ERRLOG("sigaction(SIGHUP) failed\n");
2867 goto initialize_error;
2868 }
2869 #ifdef SIGINFO
2870 sigact.sa_handler = istgt_siginfo;
2871 sigemptyset(&sigact.sa_mask);
2872 rc = sigaction(SIGINFO, &sigact, &sigoldact_info);
2873 if (rc < 0) {
2874 ISTGT_ERRLOG("sigaction(SIGINFO) failed\n");
2875 goto initialize_error;
2876 }
2877 #endif
2878 #ifdef ISTGT_USE_SIGRT
2879 if (ISTGT_SIGWAKEUP < SIGRTMIN
2880 || ISTGT_SIGWAKEUP > SIGRTMAX) {
2881 ISTGT_ERRLOG("SIGRT error\n");
2882 goto initialize_error;
2883 }
2884 #endif /* ISTGT_USE_SIGRT */
2885 sigact.sa_handler = istgt_sigwakeup;
2886 sigemptyset(&sigact.sa_mask);
2887 rc = sigaction(ISTGT_SIGWAKEUP, &sigact, &sigoldact_wakeup);
2888 if (rc < 0) {
2889 ISTGT_ERRLOG("sigaction(ISTGT_SIGWAKEUP) failed\n");
2890 goto initialize_error;
2891 }
2892 #ifdef SIGIO
2893 sigact.sa_handler = istgt_sigio;
2894 sigemptyset(&sigact.sa_mask);
2895 rc = sigaction(SIGIO, &sigact, &sigoldact_io);
2896 if (rc < 0) {
2897 ISTGT_ERRLOG("sigaction(SIGIO) failed\n");
2898 goto initialize_error;
2899 }
2900 #endif
2901 pthread_sigmask(SIG_SETMASK, NULL, &signew);
2902 sigaddset(&signew, SIGINT);
2903 sigaddset(&signew, SIGTERM);
2904 sigaddset(&signew, SIGQUIT);
2905 sigaddset(&signew, SIGHUP);
2906 #ifdef SIGINFO
2907 sigaddset(&signew, SIGINFO);
2908 #endif
2909 sigaddset(&signew, SIGUSR1);
2910 sigaddset(&signew, SIGUSR2);
2911 #ifdef SIGIO
2912 sigaddset(&signew, SIGIO);
2913 #endif
2914 sigaddset(&signew, ISTGT_SIGWAKEUP);
2915 pthread_sigmask(SIG_SETMASK, &signew, &sigold);
2916 #ifdef ISTGT_STACKSIZE
2917 rc = pthread_create(&sigthread, &istgt->attr, &istgt_sighandler,
2918 (void *) istgt);
2919 #else
2920 rc = pthread_create(&sigthread, NULL, &istgt_sighandler,
2921 (void *) istgt);
2922 #endif
2923 if (rc != 0) {
2924 ISTGT_ERRLOG("pthread_create() failed\n");
2925 goto initialize_error;
2926 }
2927 #if 0
2928 rc = pthread_detach(sigthread);
2929 if (rc != 0) {
2930 ISTGT_ERRLOG("pthread_detach() failed\n");
2931 goto initialize_error;
2932 }
2933 #endif
2934 #ifdef HAVE_PTHREAD_SET_NAME_NP
2935 pthread_set_name_np(sigthread, "sigthread");
2936 pthread_set_name_np(pthread_self(), "mainthread");
2937 #endif
2938
2939 /* create LUN threads for command queuing */
2940 rc = istgt_lu_create_threads(istgt);
2941 if (rc < 0) {
2942 ISTGT_ERRLOG("lu_create_threads() failed\n");
2943 goto initialize_error;
2944 }
2945 rc = istgt_lu_set_all_state(istgt, ISTGT_STATE_RUNNING);
2946 if (rc < 0) {
2947 ISTGT_ERRLOG("lu_set_all_state() failed\n");
2948 goto initialize_error;
2949 }
2950
2951 /* open portals */
2952 rc = istgt_open_uctl_portal(istgt);
2953 if (rc < 0) {
2954 ISTGT_ERRLOG("istgt_open_uctl_portal() failed\n");
2955 goto initialize_error;
2956 }
2957 rc = istgt_open_all_portals(istgt);
2958 if (rc < 0) {
2959 ISTGT_ERRLOG("istgt_open_all_portals() failed\n");
2960 goto initialize_error;
2961 }
2962
2963 /* write pid */
2964 rc = istgt_write_pidfile(istgt);
2965 if (rc < 0) {
2966 ISTGT_ERRLOG("istgt_write_pid() failed\n");
2967 goto initialize_error;
2968 }
2969
2970 /* accept loop */
2971 rc = istgt_acceptor(istgt);
2972 if (rc < 0) {
2973 ISTGT_ERRLOG("istgt_acceptor() failed\n");
2974 istgt_close_all_portals(istgt);
2975 istgt_close_uctl_portal(istgt);
2976 istgt_iscsi_shutdown(istgt);
2977 istgt_lu_shutdown(istgt);
2978 istgt_shutdown(istgt);
2979 istgt_close_log();
2980 config = istgt->config;
2981 istgt->config = NULL;
2982 istgt_free_config(config);
2983 exit(EXIT_FAILURE);
2984 }
2985
2986 /* wait threads */
2987 istgt_stop_conns();
2988 while (retry > 0) {
2989 if (istgt_get_active_conns() == 0) {
2990 break;
2991 }
2992 sleep(1);
2993 retry--;
2994 }
2995 ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "retry=%d\n", retry);
2996
2997 ISTGT_NOTICELOG("istgt version %s (%s) exiting\n", ISTGT_VERSION,
2998 ISTGT_EXTRA_VERSION);
2999
3000 /* stop signal thread */
3001 rc = pthread_join(sigthread, NULL);
3002 if (rc != 0) {
3003 ISTGT_ERRLOG("pthread_join() failed\n");
3004 exit (EXIT_FAILURE);
3005 }
3006
3007 /* cleanup */
3008 istgt_close_all_portals(istgt);
3009 istgt_close_uctl_portal(istgt);
3010 istgt_iscsi_shutdown(istgt);
3011 istgt_lu_shutdown(istgt);
3012 istgt_shutdown(istgt);
3013 istgt_close_log();
3014 config = istgt->config;
3015 istgt->config = NULL;
3016 istgt_free_config(config);
3017 istgt->state = ISTGT_STATE_SHUTDOWN;
3018
3019 return 0;
3020 }
3021