Deleted Added
sdiff udiff text old ( 275244 ) new ( 275245 )
full compact
1/*-
2 * Copyright (c) 2012 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Edward Tomasz Napierala under sponsorship
6 * from the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: stable/10/usr.sbin/ctld/ctld.c 275245 2014-11-29 15:34:17Z trasz $");
33
34#include <sys/types.h>
35#include <sys/time.h>
36#include <sys/socket.h>
37#include <sys/wait.h>
38#include <netinet/in.h>
39#include <arpa/inet.h>
40#include <assert.h>
41#include <ctype.h>
42#include <errno.h>
43#include <netdb.h>
44#include <signal.h>
45#include <stdbool.h>
46#include <stdio.h>
47#include <stdint.h>
48#include <stdlib.h>
49#include <string.h>
50#include <unistd.h>
51
52#include "ctld.h"
53#include "isns.h"
54
55bool proxy_mode = false;
56
57static volatile bool sighup_received = false;
58static volatile bool sigterm_received = false;
59static volatile bool sigalrm_received = false;
60
61static int nchildren = 0;
62
63static void
64usage(void)
65{
66
67 fprintf(stderr, "usage: ctld [-d][-f config-file]\n");
68 exit(1);
69}
70
71char *
72checked_strdup(const char *s)
73{
74 char *c;
75
76 c = strdup(s);
77 if (c == NULL)
78 log_err(1, "strdup");
79 return (c);
80}
81
82struct conf *
83conf_new(void)
84{
85 struct conf *conf;
86
87 conf = calloc(1, sizeof(*conf));
88 if (conf == NULL)
89 log_err(1, "calloc");
90 TAILQ_INIT(&conf->conf_targets);
91 TAILQ_INIT(&conf->conf_auth_groups);
92 TAILQ_INIT(&conf->conf_portal_groups);
93 TAILQ_INIT(&conf->conf_isns);
94
95 conf->conf_isns_period = 900;
96 conf->conf_isns_timeout = 5;
97 conf->conf_debug = 0;
98 conf->conf_timeout = 60;
99 conf->conf_maxproc = 30;
100
101 return (conf);
102}
103
104void
105conf_delete(struct conf *conf)
106{
107 struct target *targ, *tmp;
108 struct auth_group *ag, *cagtmp;
109 struct portal_group *pg, *cpgtmp;
110 struct isns *is, *istmp;
111
112 assert(conf->conf_pidfh == NULL);
113
114 TAILQ_FOREACH_SAFE(targ, &conf->conf_targets, t_next, tmp)
115 target_delete(targ);
116 TAILQ_FOREACH_SAFE(ag, &conf->conf_auth_groups, ag_next, cagtmp)
117 auth_group_delete(ag);
118 TAILQ_FOREACH_SAFE(pg, &conf->conf_portal_groups, pg_next, cpgtmp)
119 portal_group_delete(pg);
120 TAILQ_FOREACH_SAFE(is, &conf->conf_isns, i_next, istmp)
121 isns_delete(is);
122 free(conf->conf_pidfile_path);
123 free(conf);
124}
125
126static struct auth *
127auth_new(struct auth_group *ag)
128{
129 struct auth *auth;
130
131 auth = calloc(1, sizeof(*auth));
132 if (auth == NULL)
133 log_err(1, "calloc");
134 auth->a_auth_group = ag;
135 TAILQ_INSERT_TAIL(&ag->ag_auths, auth, a_next);
136 return (auth);
137}
138
139static void
140auth_delete(struct auth *auth)
141{
142 TAILQ_REMOVE(&auth->a_auth_group->ag_auths, auth, a_next);
143
144 free(auth->a_user);
145 free(auth->a_secret);
146 free(auth->a_mutual_user);
147 free(auth->a_mutual_secret);
148 free(auth);
149}
150
151const struct auth *
152auth_find(const struct auth_group *ag, const char *user)
153{
154 const struct auth *auth;
155
156 TAILQ_FOREACH(auth, &ag->ag_auths, a_next) {
157 if (strcmp(auth->a_user, user) == 0)
158 return (auth);
159 }
160
161 return (NULL);
162}
163
164static void
165auth_check_secret_length(struct auth *auth)
166{
167 size_t len;
168
169 len = strlen(auth->a_secret);
170 if (len > 16) {
171 if (auth->a_auth_group->ag_name != NULL)
172 log_warnx("secret for user \"%s\", auth-group \"%s\", "
173 "is too long; it should be at most 16 characters "
174 "long", auth->a_user, auth->a_auth_group->ag_name);
175 else
176 log_warnx("secret for user \"%s\", target \"%s\", "
177 "is too long; it should be at most 16 characters "
178 "long", auth->a_user,
179 auth->a_auth_group->ag_target->t_name);
180 }
181 if (len < 12) {
182 if (auth->a_auth_group->ag_name != NULL)
183 log_warnx("secret for user \"%s\", auth-group \"%s\", "
184 "is too short; it should be at least 12 characters "
185 "long", auth->a_user,
186 auth->a_auth_group->ag_name);
187 else
188 log_warnx("secret for user \"%s\", target \"%s\", "
189 "is too short; it should be at least 16 characters "
190 "long", auth->a_user,
191 auth->a_auth_group->ag_target->t_name);
192 }
193
194 if (auth->a_mutual_secret != NULL) {
195 len = strlen(auth->a_secret);
196 if (len > 16) {
197 if (auth->a_auth_group->ag_name != NULL)
198 log_warnx("mutual secret for user \"%s\", "
199 "auth-group \"%s\", is too long; it should "
200 "be at most 16 characters long",
201 auth->a_user, auth->a_auth_group->ag_name);
202 else
203 log_warnx("mutual secret for user \"%s\", "
204 "target \"%s\", is too long; it should "
205 "be at most 16 characters long",
206 auth->a_user,
207 auth->a_auth_group->ag_target->t_name);
208 }
209 if (len < 12) {
210 if (auth->a_auth_group->ag_name != NULL)
211 log_warnx("mutual secret for user \"%s\", "
212 "auth-group \"%s\", is too short; it "
213 "should be at least 12 characters long",
214 auth->a_user, auth->a_auth_group->ag_name);
215 else
216 log_warnx("mutual secret for user \"%s\", "
217 "target \"%s\", is too short; it should be "
218 "at least 16 characters long",
219 auth->a_user,
220 auth->a_auth_group->ag_target->t_name);
221 }
222 }
223}
224
225const struct auth *
226auth_new_chap(struct auth_group *ag, const char *user,
227 const char *secret)
228{
229 struct auth *auth;
230
231 if (ag->ag_type == AG_TYPE_UNKNOWN)
232 ag->ag_type = AG_TYPE_CHAP;
233 if (ag->ag_type != AG_TYPE_CHAP) {
234 if (ag->ag_name != NULL)
235 log_warnx("cannot mix \"chap\" authentication with "
236 "other types for auth-group \"%s\"", ag->ag_name);
237 else
238 log_warnx("cannot mix \"chap\" authentication with "
239 "other types for target \"%s\"",
240 ag->ag_target->t_name);
241 return (NULL);
242 }
243
244 auth = auth_new(ag);
245 auth->a_user = checked_strdup(user);
246 auth->a_secret = checked_strdup(secret);
247
248 auth_check_secret_length(auth);
249
250 return (auth);
251}
252
253const struct auth *
254auth_new_chap_mutual(struct auth_group *ag, const char *user,
255 const char *secret, const char *user2, const char *secret2)
256{
257 struct auth *auth;
258
259 if (ag->ag_type == AG_TYPE_UNKNOWN)
260 ag->ag_type = AG_TYPE_CHAP_MUTUAL;
261 if (ag->ag_type != AG_TYPE_CHAP_MUTUAL) {
262 if (ag->ag_name != NULL)
263 log_warnx("cannot mix \"chap-mutual\" authentication "
264 "with other types for auth-group \"%s\"",
265 ag->ag_name);
266 else
267 log_warnx("cannot mix \"chap-mutual\" authentication "
268 "with other types for target \"%s\"",
269 ag->ag_target->t_name);
270 return (NULL);
271 }
272
273 auth = auth_new(ag);
274 auth->a_user = checked_strdup(user);
275 auth->a_secret = checked_strdup(secret);
276 auth->a_mutual_user = checked_strdup(user2);
277 auth->a_mutual_secret = checked_strdup(secret2);
278
279 auth_check_secret_length(auth);
280
281 return (auth);
282}
283
284const struct auth_name *
285auth_name_new(struct auth_group *ag, const char *name)
286{
287 struct auth_name *an;
288
289 an = calloc(1, sizeof(*an));
290 if (an == NULL)
291 log_err(1, "calloc");
292 an->an_auth_group = ag;
293 an->an_initator_name = checked_strdup(name);
294 TAILQ_INSERT_TAIL(&ag->ag_names, an, an_next);
295 return (an);
296}
297
298static void
299auth_name_delete(struct auth_name *an)
300{
301 TAILQ_REMOVE(&an->an_auth_group->ag_names, an, an_next);
302
303 free(an->an_initator_name);
304 free(an);
305}
306
307bool
308auth_name_defined(const struct auth_group *ag)
309{
310 if (TAILQ_EMPTY(&ag->ag_names))
311 return (false);
312 return (true);
313}
314
315const struct auth_name *
316auth_name_find(const struct auth_group *ag, const char *name)
317{
318 const struct auth_name *auth_name;
319
320 TAILQ_FOREACH(auth_name, &ag->ag_names, an_next) {
321 if (strcmp(auth_name->an_initator_name, name) == 0)
322 return (auth_name);
323 }
324
325 return (NULL);
326}
327
328int
329auth_name_check(const struct auth_group *ag, const char *initiator_name)
330{
331 if (!auth_name_defined(ag))
332 return (0);
333
334 if (auth_name_find(ag, initiator_name) == NULL)
335 return (1);
336
337 return (0);
338}
339
340const struct auth_portal *
341auth_portal_new(struct auth_group *ag, const char *portal)
342{
343 struct auth_portal *ap;
344 char *net, *mask, *str, *tmp;
345 int len, dm, m;
346
347 ap = calloc(1, sizeof(*ap));
348 if (ap == NULL)
349 log_err(1, "calloc");
350 ap->ap_auth_group = ag;
351 ap->ap_initator_portal = checked_strdup(portal);
352 mask = str = checked_strdup(portal);
353 net = strsep(&mask, "/");
354 if (net[0] == '[')
355 net++;
356 len = strlen(net);
357 if (len == 0)
358 goto error;
359 if (net[len - 1] == ']')
360 net[len - 1] = 0;
361 if (strchr(net, ':') != NULL) {
362 struct sockaddr_in6 *sin6 =
363 (struct sockaddr_in6 *)&ap->ap_sa;
364
365 sin6->sin6_len = sizeof(*sin6);
366 sin6->sin6_family = AF_INET6;
367 if (inet_pton(AF_INET6, net, &sin6->sin6_addr) <= 0)
368 goto error;
369 dm = 128;
370 } else {
371 struct sockaddr_in *sin =
372 (struct sockaddr_in *)&ap->ap_sa;
373
374 sin->sin_len = sizeof(*sin);
375 sin->sin_family = AF_INET;
376 if (inet_pton(AF_INET, net, &sin->sin_addr) <= 0)
377 goto error;
378 dm = 32;
379 }
380 if (mask != NULL) {
381 m = strtol(mask, &tmp, 0);
382 if (m < 0 || m > dm || tmp[0] != 0)
383 goto error;
384 } else
385 m = dm;
386 ap->ap_mask = m;
387 free(str);
388 TAILQ_INSERT_TAIL(&ag->ag_portals, ap, ap_next);
389 return (ap);
390
391error:
392 log_errx(1, "Incorrect initiator portal '%s'", portal);
393 return (NULL);
394}
395
396static void
397auth_portal_delete(struct auth_portal *ap)
398{
399 TAILQ_REMOVE(&ap->ap_auth_group->ag_portals, ap, ap_next);
400
401 free(ap->ap_initator_portal);
402 free(ap);
403}
404
405bool
406auth_portal_defined(const struct auth_group *ag)
407{
408 if (TAILQ_EMPTY(&ag->ag_portals))
409 return (false);
410 return (true);
411}
412
413const struct auth_portal *
414auth_portal_find(const struct auth_group *ag, const struct sockaddr_storage *ss)
415{
416 const struct auth_portal *ap;
417 const uint8_t *a, *b;
418 int i;
419 uint8_t bmask;
420
421 TAILQ_FOREACH(ap, &ag->ag_portals, ap_next) {
422 if (ap->ap_sa.ss_family != ss->ss_family)
423 continue;
424 if (ss->ss_family == AF_INET) {
425 a = (const uint8_t *)
426 &((const struct sockaddr_in *)ss)->sin_addr;
427 b = (const uint8_t *)
428 &((const struct sockaddr_in *)&ap->ap_sa)->sin_addr;
429 } else {
430 a = (const uint8_t *)
431 &((const struct sockaddr_in6 *)ss)->sin6_addr;
432 b = (const uint8_t *)
433 &((const struct sockaddr_in6 *)&ap->ap_sa)->sin6_addr;
434 }
435 for (i = 0; i < ap->ap_mask / 8; i++) {
436 if (a[i] != b[i])
437 goto next;
438 }
439 if (ap->ap_mask % 8) {
440 bmask = 0xff << (8 - (ap->ap_mask % 8));
441 if ((a[i] & bmask) != (b[i] & bmask))
442 goto next;
443 }
444 return (ap);
445next:
446 ;
447 }
448
449 return (NULL);
450}
451
452int
453auth_portal_check(const struct auth_group *ag, const struct sockaddr_storage *sa)
454{
455
456 if (!auth_portal_defined(ag))
457 return (0);
458
459 if (auth_portal_find(ag, sa) == NULL)
460 return (1);
461
462 return (0);
463}
464
465struct auth_group *
466auth_group_new(struct conf *conf, const char *name)
467{
468 struct auth_group *ag;
469
470 if (name != NULL) {
471 ag = auth_group_find(conf, name);
472 if (ag != NULL) {
473 log_warnx("duplicated auth-group \"%s\"", name);
474 return (NULL);
475 }
476 }
477
478 ag = calloc(1, sizeof(*ag));
479 if (ag == NULL)
480 log_err(1, "calloc");
481 if (name != NULL)
482 ag->ag_name = checked_strdup(name);
483 TAILQ_INIT(&ag->ag_auths);
484 TAILQ_INIT(&ag->ag_names);
485 TAILQ_INIT(&ag->ag_portals);
486 ag->ag_conf = conf;
487 TAILQ_INSERT_TAIL(&conf->conf_auth_groups, ag, ag_next);
488
489 return (ag);
490}
491
492void
493auth_group_delete(struct auth_group *ag)
494{
495 struct auth *auth, *auth_tmp;
496 struct auth_name *auth_name, *auth_name_tmp;
497 struct auth_portal *auth_portal, *auth_portal_tmp;
498
499 TAILQ_REMOVE(&ag->ag_conf->conf_auth_groups, ag, ag_next);
500
501 TAILQ_FOREACH_SAFE(auth, &ag->ag_auths, a_next, auth_tmp)
502 auth_delete(auth);
503 TAILQ_FOREACH_SAFE(auth_name, &ag->ag_names, an_next, auth_name_tmp)
504 auth_name_delete(auth_name);
505 TAILQ_FOREACH_SAFE(auth_portal, &ag->ag_portals, ap_next,
506 auth_portal_tmp)
507 auth_portal_delete(auth_portal);
508 free(ag->ag_name);
509 free(ag);
510}
511
512struct auth_group *
513auth_group_find(const struct conf *conf, const char *name)
514{
515 struct auth_group *ag;
516
517 TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) {
518 if (ag->ag_name != NULL && strcmp(ag->ag_name, name) == 0)
519 return (ag);
520 }
521
522 return (NULL);
523}
524
525int
526auth_group_set_type(struct auth_group *ag, const char *str)
527{
528 int type;
529
530 if (strcmp(str, "none") == 0) {
531 type = AG_TYPE_NO_AUTHENTICATION;
532 } else if (strcmp(str, "deny") == 0) {
533 type = AG_TYPE_DENY;
534 } else if (strcmp(str, "chap") == 0) {
535 type = AG_TYPE_CHAP;
536 } else if (strcmp(str, "chap-mutual") == 0) {
537 type = AG_TYPE_CHAP_MUTUAL;
538 } else {
539 if (ag->ag_name != NULL)
540 log_warnx("invalid auth-type \"%s\" for auth-group "
541 "\"%s\"", str, ag->ag_name);
542 else
543 log_warnx("invalid auth-type \"%s\" for target "
544 "\"%s\"", str, ag->ag_target->t_name);
545 return (1);
546 }
547
548 if (ag->ag_type != AG_TYPE_UNKNOWN && ag->ag_type != type) {
549 if (ag->ag_name != NULL) {
550 log_warnx("cannot set auth-type to \"%s\" for "
551 "auth-group \"%s\"; already has a different "
552 "type", str, ag->ag_name);
553 } else {
554 log_warnx("cannot set auth-type to \"%s\" for target "
555 "\"%s\"; already has a different type",
556 str, ag->ag_target->t_name);
557 }
558 return (1);
559 }
560
561 ag->ag_type = type;
562
563 return (0);
564}
565
566static struct portal *
567portal_new(struct portal_group *pg)
568{
569 struct portal *portal;
570
571 portal = calloc(1, sizeof(*portal));
572 if (portal == NULL)
573 log_err(1, "calloc");
574 TAILQ_INIT(&portal->p_targets);
575 portal->p_portal_group = pg;
576 TAILQ_INSERT_TAIL(&pg->pg_portals, portal, p_next);
577 return (portal);
578}
579
580static void
581portal_delete(struct portal *portal)
582{
583
584 TAILQ_REMOVE(&portal->p_portal_group->pg_portals, portal, p_next);
585 if (portal->p_ai != NULL)
586 freeaddrinfo(portal->p_ai);
587 free(portal->p_listen);
588 free(portal);
589}
590
591struct portal_group *
592portal_group_new(struct conf *conf, const char *name)
593{
594 struct portal_group *pg;
595
596 pg = portal_group_find(conf, name);
597 if (pg != NULL) {
598 log_warnx("duplicated portal-group \"%s\"", name);
599 return (NULL);
600 }
601
602 pg = calloc(1, sizeof(*pg));
603 if (pg == NULL)
604 log_err(1, "calloc");
605 pg->pg_name = checked_strdup(name);
606 TAILQ_INIT(&pg->pg_portals);
607 pg->pg_conf = conf;
608 conf->conf_last_portal_group_tag++;
609 pg->pg_tag = conf->conf_last_portal_group_tag;
610 TAILQ_INSERT_TAIL(&conf->conf_portal_groups, pg, pg_next);
611
612 return (pg);
613}
614
615void
616portal_group_delete(struct portal_group *pg)
617{
618 struct portal *portal, *tmp;
619
620 TAILQ_REMOVE(&pg->pg_conf->conf_portal_groups, pg, pg_next);
621
622 TAILQ_FOREACH_SAFE(portal, &pg->pg_portals, p_next, tmp)
623 portal_delete(portal);
624 free(pg->pg_name);
625 free(pg);
626}
627
628struct portal_group *
629portal_group_find(const struct conf *conf, const char *name)
630{
631 struct portal_group *pg;
632
633 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
634 if (strcmp(pg->pg_name, name) == 0)
635 return (pg);
636 }
637
638 return (NULL);
639}
640
641static int
642parse_addr_port(char *arg, const char *def_port, struct addrinfo **ai)
643{
644 struct addrinfo hints;
645 char *addr, *ch;
646 const char *port;
647 int error, colons = 0;
648
649 if (arg[0] == '[') {
650 /*
651 * IPv6 address in square brackets, perhaps with port.
652 */
653 arg++;
654 addr = strsep(&arg, "]");
655 if (arg == NULL)
656 return (1);
657 if (arg[0] == '\0') {
658 port = def_port;
659 } else if (arg[0] == ':') {
660 port = arg + 1;
661 } else
662 return (1);
663 } else {
664 /*
665 * Either IPv6 address without brackets - and without
666 * a port - or IPv4 address. Just count the colons.
667 */
668 for (ch = arg; *ch != '\0'; ch++) {
669 if (*ch == ':')
670 colons++;
671 }
672 if (colons > 1) {
673 addr = arg;
674 port = def_port;
675 } else {
676 addr = strsep(&arg, ":");
677 if (arg == NULL)
678 port = def_port;
679 else
680 port = arg;
681 }
682 }
683
684 memset(&hints, 0, sizeof(hints));
685 hints.ai_family = PF_UNSPEC;
686 hints.ai_socktype = SOCK_STREAM;
687 hints.ai_flags = AI_PASSIVE;
688 error = getaddrinfo(addr, port, &hints, ai);
689 if (error != 0)
690 return (1);
691 return (0);
692}
693
694int
695portal_group_add_listen(struct portal_group *pg, const char *value, bool iser)
696{
697 struct portal *portal;
698
699 portal = portal_new(pg);
700 portal->p_listen = checked_strdup(value);
701 portal->p_iser = iser;
702
703 if (parse_addr_port(portal->p_listen, "3260", &portal->p_ai)) {
704 log_warnx("invalid listen address %s", portal->p_listen);
705 portal_delete(portal);
706 return (1);
707 }
708
709 /*
710 * XXX: getaddrinfo(3) may return multiple addresses; we should turn
711 * those into multiple portals.
712 */
713
714 return (0);
715}
716
717int
718isns_new(struct conf *conf, const char *addr)
719{
720 struct isns *isns;
721
722 isns = calloc(1, sizeof(*isns));
723 if (isns == NULL)
724 log_err(1, "calloc");
725 isns->i_conf = conf;
726 TAILQ_INSERT_TAIL(&conf->conf_isns, isns, i_next);
727 isns->i_addr = checked_strdup(addr);
728
729 if (parse_addr_port(isns->i_addr, "3205", &isns->i_ai)) {
730 log_warnx("invalid iSNS address %s", isns->i_addr);
731 isns_delete(isns);
732 return (1);
733 }
734
735 /*
736 * XXX: getaddrinfo(3) may return multiple addresses; we should turn
737 * those into multiple servers.
738 */
739
740 return (0);
741}
742
743void
744isns_delete(struct isns *isns)
745{
746
747 TAILQ_REMOVE(&isns->i_conf->conf_isns, isns, i_next);
748 free(isns->i_addr);
749 if (isns->i_ai != NULL)
750 freeaddrinfo(isns->i_ai);
751 free(isns);
752}
753
754static int
755isns_do_connect(struct isns *isns)
756{
757 int s;
758
759 s = socket(isns->i_ai->ai_family, isns->i_ai->ai_socktype,
760 isns->i_ai->ai_protocol);
761 if (s < 0) {
762 log_warn("socket(2) failed for %s", isns->i_addr);
763 return (-1);
764 }
765 if (connect(s, isns->i_ai->ai_addr, isns->i_ai->ai_addrlen)) {
766 log_warn("connect(2) failed for %s", isns->i_addr);
767 close(s);
768 return (-1);
769 }
770 return(s);
771}
772
773static int
774isns_do_register(struct isns *isns, int s, const char *hostname)
775{
776 struct conf *conf = isns->i_conf;
777 struct target *target;
778 struct portal *portal;
779 struct portal_group *pg;
780 struct isns_req *req;
781 int res = 0;
782 uint32_t error;
783
784 req = isns_req_create(ISNS_FUNC_DEVATTRREG, ISNS_FLAG_CLIENT);
785 isns_req_add_str(req, 32, TAILQ_FIRST(&conf->conf_targets)->t_name);
786 isns_req_add_delim(req);
787 isns_req_add_str(req, 1, hostname);
788 isns_req_add_32(req, 2, 2); /* 2 -- iSCSI */
789 isns_req_add_32(req, 6, conf->conf_isns_period);
790 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
791 if (pg->pg_unassigned)
792 continue;
793 TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
794 isns_req_add_addr(req, 16, portal->p_ai);
795 isns_req_add_port(req, 17, portal->p_ai);
796 }
797 }
798 TAILQ_FOREACH(target, &conf->conf_targets, t_next) {
799 isns_req_add_str(req, 32, target->t_name);
800 isns_req_add_32(req, 33, 1); /* 1 -- Target*/
801 if (target->t_alias != NULL)
802 isns_req_add_str(req, 34, target->t_alias);
803 pg = target->t_portal_group;
804 isns_req_add_32(req, 51, pg->pg_tag);
805 TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
806 isns_req_add_addr(req, 49, portal->p_ai);
807 isns_req_add_port(req, 50, portal->p_ai);
808 }
809 }
810 res = isns_req_send(s, req);
811 if (res < 0) {
812 log_warn("send(2) failed for %s", isns->i_addr);
813 goto quit;
814 }
815 res = isns_req_receive(s, req);
816 if (res < 0) {
817 log_warn("receive(2) failed for %s", isns->i_addr);
818 goto quit;
819 }
820 error = isns_req_get_status(req);
821 if (error != 0) {
822 log_warnx("iSNS register error %d for %s", error, isns->i_addr);
823 res = -1;
824 }
825quit:
826 isns_req_free(req);
827 return (res);
828}
829
830static int
831isns_do_check(struct isns *isns, int s, const char *hostname)
832{
833 struct conf *conf = isns->i_conf;
834 struct isns_req *req;
835 int res = 0;
836 uint32_t error;
837
838 req = isns_req_create(ISNS_FUNC_DEVATTRQRY, ISNS_FLAG_CLIENT);
839 isns_req_add_str(req, 32, TAILQ_FIRST(&conf->conf_targets)->t_name);
840 isns_req_add_str(req, 1, hostname);
841 isns_req_add_delim(req);
842 isns_req_add(req, 2, 0, NULL);
843 res = isns_req_send(s, req);
844 if (res < 0) {
845 log_warn("send(2) failed for %s", isns->i_addr);
846 goto quit;
847 }
848 res = isns_req_receive(s, req);
849 if (res < 0) {
850 log_warn("receive(2) failed for %s", isns->i_addr);
851 goto quit;
852 }
853 error = isns_req_get_status(req);
854 if (error != 0) {
855 log_warnx("iSNS check error %d for %s", error, isns->i_addr);
856 res = -1;
857 }
858quit:
859 isns_req_free(req);
860 return (res);
861}
862
863static int
864isns_do_deregister(struct isns *isns, int s, const char *hostname)
865{
866 struct conf *conf = isns->i_conf;
867 struct isns_req *req;
868 int res = 0;
869 uint32_t error;
870
871 req = isns_req_create(ISNS_FUNC_DEVDEREG, ISNS_FLAG_CLIENT);
872 isns_req_add_str(req, 32, TAILQ_FIRST(&conf->conf_targets)->t_name);
873 isns_req_add_delim(req);
874 isns_req_add_str(req, 1, hostname);
875 res = isns_req_send(s, req);
876 if (res < 0) {
877 log_warn("send(2) failed for %s", isns->i_addr);
878 goto quit;
879 }
880 res = isns_req_receive(s, req);
881 if (res < 0) {
882 log_warn("receive(2) failed for %s", isns->i_addr);
883 goto quit;
884 }
885 error = isns_req_get_status(req);
886 if (error != 0) {
887 log_warnx("iSNS deregister error %d for %s", error, isns->i_addr);
888 res = -1;
889 }
890quit:
891 isns_req_free(req);
892 return (res);
893}
894
895void
896isns_register(struct isns *isns, struct isns *oldisns)
897{
898 struct conf *conf = isns->i_conf;
899 int s, res;
900 char hostname[256];
901
902 if (TAILQ_EMPTY(&conf->conf_targets) ||
903 TAILQ_EMPTY(&conf->conf_portal_groups))
904 return;
905 set_timeout(conf->conf_isns_timeout, false);
906 s = isns_do_connect(isns);
907 if (s < 0) {
908 set_timeout(0, false);
909 return;
910 }
911 gethostname(hostname, sizeof(hostname));
912
913 if (oldisns == NULL || TAILQ_EMPTY(&oldisns->i_conf->conf_targets))
914 oldisns = isns;
915 res = isns_do_deregister(oldisns, s, hostname);
916 res = isns_do_register(isns, s, hostname);
917 close(s);
918 set_timeout(0, false);
919}
920
921void
922isns_check(struct isns *isns)
923{
924 struct conf *conf = isns->i_conf;
925 int s, res;
926 char hostname[256];
927
928 if (TAILQ_EMPTY(&conf->conf_targets) ||
929 TAILQ_EMPTY(&conf->conf_portal_groups))
930 return;
931 set_timeout(conf->conf_isns_timeout, false);
932 s = isns_do_connect(isns);
933 if (s < 0) {
934 set_timeout(0, false);
935 return;
936 }
937 gethostname(hostname, sizeof(hostname));
938
939 res = isns_do_check(isns, s, hostname);
940 if (res < 0) {
941 res = isns_do_deregister(isns, s, hostname);
942 res = isns_do_register(isns, s, hostname);
943 }
944 close(s);
945 set_timeout(0, false);
946}
947
948void
949isns_deregister(struct isns *isns)
950{
951 struct conf *conf = isns->i_conf;
952 int s, res;
953 char hostname[256];
954
955 if (TAILQ_EMPTY(&conf->conf_targets) ||
956 TAILQ_EMPTY(&conf->conf_portal_groups))
957 return;
958 set_timeout(conf->conf_isns_timeout, false);
959 s = isns_do_connect(isns);
960 if (s < 0)
961 return;
962 gethostname(hostname, sizeof(hostname));
963
964 res = isns_do_deregister(isns, s, hostname);
965 close(s);
966 set_timeout(0, false);
967}
968
969int
970portal_group_set_filter(struct portal_group *pg, const char *str)
971{
972 int filter;
973
974 if (strcmp(str, "none") == 0) {
975 filter = PG_FILTER_NONE;
976 } else if (strcmp(str, "portal") == 0) {
977 filter = PG_FILTER_PORTAL;
978 } else if (strcmp(str, "portal-name") == 0) {
979 filter = PG_FILTER_PORTAL_NAME;
980 } else if (strcmp(str, "portal-name-auth") == 0) {
981 filter = PG_FILTER_PORTAL_NAME_AUTH;
982 } else {
983 log_warnx("invalid discovery-filter \"%s\" for portal-group "
984 "\"%s\"; valid values are \"none\", \"portal\", "
985 "\"portal-name\", and \"portal-name-auth\"",
986 str, pg->pg_name);
987 return (1);
988 }
989
990 if (pg->pg_discovery_filter != PG_FILTER_UNKNOWN &&
991 pg->pg_discovery_filter != filter) {
992 log_warnx("cannot set discovery-filter to \"%s\" for "
993 "portal-group \"%s\"; already has a different "
994 "value", str, pg->pg_name);
995 return (1);
996 }
997
998 pg->pg_discovery_filter = filter;
999
1000 return (0);
1001}
1002
1003static bool
1004valid_hex(const char ch)
1005{
1006 switch (ch) {
1007 case '0':
1008 case '1':
1009 case '2':
1010 case '3':
1011 case '4':
1012 case '5':
1013 case '6':
1014 case '7':
1015 case '8':
1016 case '9':
1017 case 'a':
1018 case 'A':
1019 case 'b':
1020 case 'B':
1021 case 'c':
1022 case 'C':
1023 case 'd':
1024 case 'D':
1025 case 'e':
1026 case 'E':
1027 case 'f':
1028 case 'F':
1029 return (true);
1030 default:
1031 return (false);
1032 }
1033}
1034
1035bool
1036valid_iscsi_name(const char *name)
1037{
1038 int i;
1039
1040 if (strlen(name) >= MAX_NAME_LEN) {
1041 log_warnx("overlong name for target \"%s\"; max length allowed "
1042 "by iSCSI specification is %d characters",
1043 name, MAX_NAME_LEN);
1044 return (false);
1045 }
1046
1047 /*
1048 * In the cases below, we don't return an error, just in case the admin
1049 * was right, and we're wrong.
1050 */
1051 if (strncasecmp(name, "iqn.", strlen("iqn.")) == 0) {
1052 for (i = strlen("iqn."); name[i] != '\0'; i++) {
1053 /*
1054 * XXX: We should verify UTF-8 normalisation, as defined
1055 * by 3.2.6.2: iSCSI Name Encoding.
1056 */
1057 if (isalnum(name[i]))
1058 continue;
1059 if (name[i] == '-' || name[i] == '.' || name[i] == ':')
1060 continue;
1061 log_warnx("invalid character \"%c\" in target name "
1062 "\"%s\"; allowed characters are letters, digits, "
1063 "'-', '.', and ':'", name[i], name);
1064 break;
1065 }
1066 /*
1067 * XXX: Check more stuff: valid date and a valid reversed domain.
1068 */
1069 } else if (strncasecmp(name, "eui.", strlen("eui.")) == 0) {
1070 if (strlen(name) != strlen("eui.") + 16)
1071 log_warnx("invalid target name \"%s\"; the \"eui.\" "
1072 "should be followed by exactly 16 hexadecimal "
1073 "digits", name);
1074 for (i = strlen("eui."); name[i] != '\0'; i++) {
1075 if (!valid_hex(name[i])) {
1076 log_warnx("invalid character \"%c\" in target "
1077 "name \"%s\"; allowed characters are 1-9 "
1078 "and A-F", name[i], name);
1079 break;
1080 }
1081 }
1082 } else if (strncasecmp(name, "naa.", strlen("naa.")) == 0) {
1083 if (strlen(name) > strlen("naa.") + 32)
1084 log_warnx("invalid target name \"%s\"; the \"naa.\" "
1085 "should be followed by at most 32 hexadecimal "
1086 "digits", name);
1087 for (i = strlen("naa."); name[i] != '\0'; i++) {
1088 if (!valid_hex(name[i])) {
1089 log_warnx("invalid character \"%c\" in target "
1090 "name \"%s\"; allowed characters are 1-9 "
1091 "and A-F", name[i], name);
1092 break;
1093 }
1094 }
1095 } else {
1096 log_warnx("invalid target name \"%s\"; should start with "
1097 "either \".iqn\", \"eui.\", or \"naa.\"",
1098 name);
1099 }
1100 return (true);
1101}
1102
1103struct target *
1104target_new(struct conf *conf, const char *name)
1105{
1106 struct target *targ;
1107 int i, len;
1108
1109 targ = target_find(conf, name);
1110 if (targ != NULL) {
1111 log_warnx("duplicated target \"%s\"", name);
1112 return (NULL);
1113 }
1114 if (valid_iscsi_name(name) == false) {
1115 log_warnx("target name \"%s\" is invalid", name);
1116 return (NULL);
1117 }
1118 targ = calloc(1, sizeof(*targ));
1119 if (targ == NULL)
1120 log_err(1, "calloc");
1121 targ->t_name = checked_strdup(name);
1122
1123 /*
1124 * RFC 3722 requires us to normalize the name to lowercase.
1125 */
1126 len = strlen(name);
1127 for (i = 0; i < len; i++)
1128 targ->t_name[i] = tolower(targ->t_name[i]);
1129
1130 TAILQ_INIT(&targ->t_luns);
1131 targ->t_conf = conf;
1132 TAILQ_INSERT_TAIL(&conf->conf_targets, targ, t_next);
1133
1134 return (targ);
1135}
1136
1137void
1138target_delete(struct target *targ)
1139{
1140 struct lun *lun, *tmp;
1141
1142 TAILQ_REMOVE(&targ->t_conf->conf_targets, targ, t_next);
1143
1144 TAILQ_FOREACH_SAFE(lun, &targ->t_luns, l_next, tmp)
1145 lun_delete(lun);
1146 free(targ->t_name);
1147 free(targ);
1148}
1149
1150struct target *
1151target_find(struct conf *conf, const char *name)
1152{
1153 struct target *targ;
1154
1155 TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
1156 if (strcasecmp(targ->t_name, name) == 0)
1157 return (targ);
1158 }
1159
1160 return (NULL);
1161}
1162
1163struct lun *
1164lun_new(struct target *targ, int lun_id)
1165{
1166 struct lun *lun;
1167
1168 lun = lun_find(targ, lun_id);
1169 if (lun != NULL) {
1170 log_warnx("duplicated lun %d for target \"%s\"",
1171 lun_id, targ->t_name);
1172 return (NULL);
1173 }
1174
1175 lun = calloc(1, sizeof(*lun));
1176 if (lun == NULL)
1177 log_err(1, "calloc");
1178 lun->l_lun = lun_id;
1179 TAILQ_INIT(&lun->l_options);
1180 lun->l_target = targ;
1181 TAILQ_INSERT_TAIL(&targ->t_luns, lun, l_next);
1182
1183 return (lun);
1184}
1185
1186void
1187lun_delete(struct lun *lun)
1188{
1189 struct lun_option *lo, *tmp;
1190
1191 TAILQ_REMOVE(&lun->l_target->t_luns, lun, l_next);
1192
1193 TAILQ_FOREACH_SAFE(lo, &lun->l_options, lo_next, tmp)
1194 lun_option_delete(lo);
1195 free(lun->l_backend);
1196 free(lun->l_device_id);
1197 free(lun->l_path);
1198 free(lun->l_serial);
1199 free(lun);
1200}
1201
1202struct lun *
1203lun_find(const struct target *targ, int lun_id)
1204{
1205 struct lun *lun;
1206
1207 TAILQ_FOREACH(lun, &targ->t_luns, l_next) {
1208 if (lun->l_lun == lun_id)
1209 return (lun);
1210 }
1211
1212 return (NULL);
1213}
1214
1215void
1216lun_set_backend(struct lun *lun, const char *value)
1217{
1218 free(lun->l_backend);
1219 lun->l_backend = checked_strdup(value);
1220}
1221
1222void
1223lun_set_blocksize(struct lun *lun, size_t value)
1224{
1225
1226 lun->l_blocksize = value;
1227}
1228
1229void
1230lun_set_device_id(struct lun *lun, const char *value)
1231{
1232 free(lun->l_device_id);
1233 lun->l_device_id = checked_strdup(value);
1234}
1235
1236void
1237lun_set_path(struct lun *lun, const char *value)
1238{
1239 free(lun->l_path);
1240 lun->l_path = checked_strdup(value);
1241}
1242
1243void
1244lun_set_serial(struct lun *lun, const char *value)
1245{
1246 free(lun->l_serial);
1247 lun->l_serial = checked_strdup(value);
1248}
1249
1250void
1251lun_set_size(struct lun *lun, size_t value)
1252{
1253
1254 lun->l_size = value;
1255}
1256
1257void
1258lun_set_ctl_lun(struct lun *lun, uint32_t value)
1259{
1260
1261 lun->l_ctl_lun = value;
1262}
1263
1264struct lun_option *
1265lun_option_new(struct lun *lun, const char *name, const char *value)
1266{
1267 struct lun_option *lo;
1268
1269 lo = lun_option_find(lun, name);
1270 if (lo != NULL) {
1271 log_warnx("duplicated lun option %s for lun %d, target \"%s\"",
1272 name, lun->l_lun, lun->l_target->t_name);
1273 return (NULL);
1274 }
1275
1276 lo = calloc(1, sizeof(*lo));
1277 if (lo == NULL)
1278 log_err(1, "calloc");
1279 lo->lo_name = checked_strdup(name);
1280 lo->lo_value = checked_strdup(value);
1281 lo->lo_lun = lun;
1282 TAILQ_INSERT_TAIL(&lun->l_options, lo, lo_next);
1283
1284 return (lo);
1285}
1286
1287void
1288lun_option_delete(struct lun_option *lo)
1289{
1290
1291 TAILQ_REMOVE(&lo->lo_lun->l_options, lo, lo_next);
1292
1293 free(lo->lo_name);
1294 free(lo->lo_value);
1295 free(lo);
1296}
1297
1298struct lun_option *
1299lun_option_find(const struct lun *lun, const char *name)
1300{
1301 struct lun_option *lo;
1302
1303 TAILQ_FOREACH(lo, &lun->l_options, lo_next) {
1304 if (strcmp(lo->lo_name, name) == 0)
1305 return (lo);
1306 }
1307
1308 return (NULL);
1309}
1310
1311void
1312lun_option_set(struct lun_option *lo, const char *value)
1313{
1314
1315 free(lo->lo_value);
1316 lo->lo_value = checked_strdup(value);
1317}
1318
1319static struct connection *
1320connection_new(struct portal *portal, int fd, const char *host,
1321 const struct sockaddr *client_sa)
1322{
1323 struct connection *conn;
1324
1325 conn = calloc(1, sizeof(*conn));
1326 if (conn == NULL)
1327 log_err(1, "calloc");
1328 conn->conn_portal = portal;
1329 conn->conn_socket = fd;
1330 conn->conn_initiator_addr = checked_strdup(host);
1331 memcpy(&conn->conn_initiator_sa, client_sa, client_sa->sa_len);
1332
1333 /*
1334 * Default values, from RFC 3720, section 12.
1335 */
1336 conn->conn_max_data_segment_length = 8192;
1337 conn->conn_max_burst_length = 262144;
1338 conn->conn_immediate_data = true;
1339
1340 return (conn);
1341}
1342
1343#if 0
1344static void
1345conf_print(struct conf *conf)
1346{
1347 struct auth_group *ag;
1348 struct auth *auth;
1349 struct auth_name *auth_name;
1350 struct auth_portal *auth_portal;
1351 struct portal_group *pg;
1352 struct portal *portal;
1353 struct target *targ;
1354 struct lun *lun;
1355 struct lun_option *lo;
1356
1357 TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) {
1358 fprintf(stderr, "auth-group %s {\n", ag->ag_name);
1359 TAILQ_FOREACH(auth, &ag->ag_auths, a_next)
1360 fprintf(stderr, "\t chap-mutual %s %s %s %s\n",
1361 auth->a_user, auth->a_secret,
1362 auth->a_mutual_user, auth->a_mutual_secret);
1363 TAILQ_FOREACH(auth_name, &ag->ag_names, an_next)
1364 fprintf(stderr, "\t initiator-name %s\n",
1365 auth_name->an_initator_name);
1366 TAILQ_FOREACH(auth_portal, &ag->ag_portals, an_next)
1367 fprintf(stderr, "\t initiator-portal %s\n",
1368 auth_portal->an_initator_portal);
1369 fprintf(stderr, "}\n");
1370 }
1371 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
1372 fprintf(stderr, "portal-group %s {\n", pg->pg_name);
1373 TAILQ_FOREACH(portal, &pg->pg_portals, p_next)
1374 fprintf(stderr, "\t listen %s\n", portal->p_listen);
1375 fprintf(stderr, "}\n");
1376 }
1377 TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
1378 fprintf(stderr, "target %s {\n", targ->t_name);
1379 if (targ->t_alias != NULL)
1380 fprintf(stderr, "\t alias %s\n", targ->t_alias);
1381 TAILQ_FOREACH(lun, &targ->t_luns, l_next) {
1382 fprintf(stderr, "\tlun %d {\n", lun->l_lun);
1383 fprintf(stderr, "\t\tpath %s\n", lun->l_path);
1384 TAILQ_FOREACH(lo, &lun->l_options, lo_next)
1385 fprintf(stderr, "\t\toption %s %s\n",
1386 lo->lo_name, lo->lo_value);
1387 fprintf(stderr, "\t}\n");
1388 }
1389 fprintf(stderr, "}\n");
1390 }
1391}
1392#endif
1393
1394static int
1395conf_verify_lun(struct lun *lun)
1396{
1397 const struct lun *lun2;
1398 const struct target *targ2;
1399
1400 if (lun->l_backend == NULL)
1401 lun_set_backend(lun, "block");
1402 if (strcmp(lun->l_backend, "block") == 0) {
1403 if (lun->l_path == NULL) {
1404 log_warnx("missing path for lun %d, target \"%s\"",
1405 lun->l_lun, lun->l_target->t_name);
1406 return (1);
1407 }
1408 } else if (strcmp(lun->l_backend, "ramdisk") == 0) {
1409 if (lun->l_size == 0) {
1410 log_warnx("missing size for ramdisk-backed lun %d, "
1411 "target \"%s\"", lun->l_lun, lun->l_target->t_name);
1412 return (1);
1413 }
1414 if (lun->l_path != NULL) {
1415 log_warnx("path must not be specified "
1416 "for ramdisk-backed lun %d, target \"%s\"",
1417 lun->l_lun, lun->l_target->t_name);
1418 return (1);
1419 }
1420 }
1421 if (lun->l_lun < 0 || lun->l_lun > 255) {
1422 log_warnx("invalid lun number for lun %d, target \"%s\"; "
1423 "must be between 0 and 255", lun->l_lun,
1424 lun->l_target->t_name);
1425 return (1);
1426 }
1427 if (lun->l_blocksize == 0) {
1428 lun_set_blocksize(lun, DEFAULT_BLOCKSIZE);
1429 } else if (lun->l_blocksize < 0) {
1430 log_warnx("invalid blocksize for lun %d, target \"%s\"; "
1431 "must be larger than 0", lun->l_lun, lun->l_target->t_name);
1432 return (1);
1433 }
1434 if (lun->l_size != 0 && lun->l_size % lun->l_blocksize != 0) {
1435 log_warnx("invalid size for lun %d, target \"%s\"; "
1436 "must be multiple of blocksize", lun->l_lun,
1437 lun->l_target->t_name);
1438 return (1);
1439 }
1440 TAILQ_FOREACH(targ2, &lun->l_target->t_conf->conf_targets, t_next) {
1441 TAILQ_FOREACH(lun2, &targ2->t_luns, l_next) {
1442 if (lun == lun2)
1443 continue;
1444 if (lun->l_path != NULL && lun2->l_path != NULL &&
1445 strcmp(lun->l_path, lun2->l_path) == 0) {
1446 log_debugx("WARNING: path \"%s\" duplicated "
1447 "between lun %d, target \"%s\", and "
1448 "lun %d, target \"%s\"", lun->l_path,
1449 lun->l_lun, lun->l_target->t_name,
1450 lun2->l_lun, lun2->l_target->t_name);
1451 }
1452 }
1453 }
1454
1455 return (0);
1456}
1457
1458int
1459conf_verify(struct conf *conf)
1460{
1461 struct auth_group *ag;
1462 struct portal_group *pg;
1463 struct target *targ;
1464 struct lun *lun;
1465 bool found;
1466 int error;
1467
1468 if (conf->conf_pidfile_path == NULL)
1469 conf->conf_pidfile_path = checked_strdup(DEFAULT_PIDFILE);
1470
1471 TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
1472 if (targ->t_auth_group == NULL) {
1473 targ->t_auth_group = auth_group_find(conf,
1474 "default");
1475 assert(targ->t_auth_group != NULL);
1476 }
1477 if (targ->t_portal_group == NULL) {
1478 targ->t_portal_group = portal_group_find(conf,
1479 "default");
1480 assert(targ->t_portal_group != NULL);
1481 }
1482 found = false;
1483 TAILQ_FOREACH(lun, &targ->t_luns, l_next) {
1484 error = conf_verify_lun(lun);
1485 if (error != 0)
1486 return (error);
1487 found = true;
1488 }
1489 if (!found) {
1490 log_warnx("no LUNs defined for target \"%s\"",
1491 targ->t_name);
1492 }
1493 }
1494 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
1495 assert(pg->pg_name != NULL);
1496 if (pg->pg_discovery_auth_group == NULL) {
1497 pg->pg_discovery_auth_group =
1498 auth_group_find(conf, "default");
1499 assert(pg->pg_discovery_auth_group != NULL);
1500 }
1501
1502 if (pg->pg_discovery_filter == PG_FILTER_UNKNOWN)
1503 pg->pg_discovery_filter = PG_FILTER_NONE;
1504
1505 TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
1506 if (targ->t_portal_group == pg)
1507 break;
1508 }
1509 if (targ == NULL) {
1510 if (strcmp(pg->pg_name, "default") != 0)
1511 log_warnx("portal-group \"%s\" not assigned "
1512 "to any target", pg->pg_name);
1513 pg->pg_unassigned = true;
1514 } else
1515 pg->pg_unassigned = false;
1516 }
1517 TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) {
1518 if (ag->ag_name == NULL)
1519 assert(ag->ag_target != NULL);
1520 else
1521 assert(ag->ag_target == NULL);
1522
1523 found = false;
1524 TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
1525 if (targ->t_auth_group == ag) {
1526 found = true;
1527 break;
1528 }
1529 }
1530 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
1531 if (pg->pg_discovery_auth_group == ag) {
1532 found = true;
1533 break;
1534 }
1535 }
1536 if (!found && ag->ag_name != NULL &&
1537 strcmp(ag->ag_name, "default") != 0 &&
1538 strcmp(ag->ag_name, "no-authentication") != 0 &&
1539 strcmp(ag->ag_name, "no-access") != 0) {
1540 log_warnx("auth-group \"%s\" not assigned "
1541 "to any target", ag->ag_name);
1542 }
1543 }
1544
1545 return (0);
1546}
1547
1548static int
1549conf_apply(struct conf *oldconf, struct conf *newconf)
1550{
1551 struct target *oldtarg, *newtarg, *tmptarg;
1552 struct lun *oldlun, *newlun, *tmplun;
1553 struct portal_group *oldpg, *newpg;
1554 struct portal *oldp, *newp;
1555 struct isns *oldns, *newns;
1556 pid_t otherpid;
1557 int changed, cumulated_error = 0, error;
1558 int one = 1;
1559
1560 if (oldconf->conf_debug != newconf->conf_debug) {
1561 log_debugx("changing debug level to %d", newconf->conf_debug);
1562 log_init(newconf->conf_debug);
1563 }
1564
1565 if (oldconf->conf_pidfh != NULL) {
1566 assert(oldconf->conf_pidfile_path != NULL);
1567 if (newconf->conf_pidfile_path != NULL &&
1568 strcmp(oldconf->conf_pidfile_path,
1569 newconf->conf_pidfile_path) == 0) {
1570 newconf->conf_pidfh = oldconf->conf_pidfh;
1571 oldconf->conf_pidfh = NULL;
1572 } else {
1573 log_debugx("removing pidfile %s",
1574 oldconf->conf_pidfile_path);
1575 pidfile_remove(oldconf->conf_pidfh);
1576 oldconf->conf_pidfh = NULL;
1577 }
1578 }
1579
1580 if (newconf->conf_pidfh == NULL && newconf->conf_pidfile_path != NULL) {
1581 log_debugx("opening pidfile %s", newconf->conf_pidfile_path);
1582 newconf->conf_pidfh =
1583 pidfile_open(newconf->conf_pidfile_path, 0600, &otherpid);
1584 if (newconf->conf_pidfh == NULL) {
1585 if (errno == EEXIST)
1586 log_errx(1, "daemon already running, pid: %jd.",
1587 (intmax_t)otherpid);
1588 log_err(1, "cannot open or create pidfile \"%s\"",
1589 newconf->conf_pidfile_path);
1590 }
1591 }
1592
1593 /* Deregister on removed iSNS servers. */
1594 TAILQ_FOREACH(oldns, &oldconf->conf_isns, i_next) {
1595 TAILQ_FOREACH(newns, &newconf->conf_isns, i_next) {
1596 if (strcmp(oldns->i_addr, newns->i_addr) == 0)
1597 break;
1598 }
1599 if (newns == NULL)
1600 isns_deregister(oldns);
1601 }
1602
1603 /*
1604 * XXX: If target or lun removal fails, we should somehow "move"
1605 * the old lun or target into newconf, so that subsequent
1606 * conf_apply() would try to remove them again. That would
1607 * be somewhat hairy, though, and lun deletion failures don't
1608 * really happen, so leave it as it is for now.
1609 */
1610 TAILQ_FOREACH_SAFE(oldtarg, &oldconf->conf_targets, t_next, tmptarg) {
1611 /*
1612 * First, remove any targets present in the old configuration
1613 * and missing in the new one.
1614 */
1615 newtarg = target_find(newconf, oldtarg->t_name);
1616 if (newtarg == NULL) {
1617 TAILQ_FOREACH_SAFE(oldlun, &oldtarg->t_luns, l_next,
1618 tmplun) {
1619 log_debugx("target %s not found in new "
1620 "configuration; removing its lun %d, "
1621 "backed by CTL lun %d",
1622 oldtarg->t_name, oldlun->l_lun,
1623 oldlun->l_ctl_lun);
1624 error = kernel_lun_remove(oldlun);
1625 if (error != 0) {
1626 log_warnx("failed to remove lun %d, "
1627 "target %s, CTL lun %d",
1628 oldlun->l_lun, oldtarg->t_name,
1629 oldlun->l_ctl_lun);
1630 cumulated_error++;
1631 }
1632 }
1633 kernel_port_remove(oldtarg);
1634 continue;
1635 }
1636
1637 /*
1638 * Second, remove any LUNs present in the old target
1639 * and missing in the new one.
1640 */
1641 TAILQ_FOREACH_SAFE(oldlun, &oldtarg->t_luns, l_next, tmplun) {
1642 newlun = lun_find(newtarg, oldlun->l_lun);
1643 if (newlun == NULL) {
1644 log_debugx("lun %d, target %s, CTL lun %d "
1645 "not found in new configuration; "
1646 "removing", oldlun->l_lun, oldtarg->t_name,
1647 oldlun->l_ctl_lun);
1648 error = kernel_lun_remove(oldlun);
1649 if (error != 0) {
1650 log_warnx("failed to remove lun %d, "
1651 "target %s, CTL lun %d",
1652 oldlun->l_lun, oldtarg->t_name,
1653 oldlun->l_ctl_lun);
1654 cumulated_error++;
1655 }
1656 continue;
1657 }
1658
1659 /*
1660 * Also remove the LUNs changed by more than size.
1661 */
1662 changed = 0;
1663 assert(oldlun->l_backend != NULL);
1664 assert(newlun->l_backend != NULL);
1665 if (strcmp(newlun->l_backend, oldlun->l_backend) != 0) {
1666 log_debugx("backend for lun %d, target %s, "
1667 "CTL lun %d changed; removing",
1668 oldlun->l_lun, oldtarg->t_name,
1669 oldlun->l_ctl_lun);
1670 changed = 1;
1671 }
1672 if (oldlun->l_blocksize != newlun->l_blocksize) {
1673 log_debugx("blocksize for lun %d, target %s, "
1674 "CTL lun %d changed; removing",
1675 oldlun->l_lun, oldtarg->t_name,
1676 oldlun->l_ctl_lun);
1677 changed = 1;
1678 }
1679 if (newlun->l_device_id != NULL &&
1680 (oldlun->l_device_id == NULL ||
1681 strcmp(oldlun->l_device_id, newlun->l_device_id) !=
1682 0)) {
1683 log_debugx("device-id for lun %d, target %s, "
1684 "CTL lun %d changed; removing",
1685 oldlun->l_lun, oldtarg->t_name,
1686 oldlun->l_ctl_lun);
1687 changed = 1;
1688 }
1689 if (newlun->l_path != NULL &&
1690 (oldlun->l_path == NULL ||
1691 strcmp(oldlun->l_path, newlun->l_path) != 0)) {
1692 log_debugx("path for lun %d, target %s, "
1693 "CTL lun %d, changed; removing",
1694 oldlun->l_lun, oldtarg->t_name,
1695 oldlun->l_ctl_lun);
1696 changed = 1;
1697 }
1698 if (newlun->l_serial != NULL &&
1699 (oldlun->l_serial == NULL ||
1700 strcmp(oldlun->l_serial, newlun->l_serial) != 0)) {
1701 log_debugx("serial for lun %d, target %s, "
1702 "CTL lun %d changed; removing",
1703 oldlun->l_lun, oldtarg->t_name,
1704 oldlun->l_ctl_lun);
1705 changed = 1;
1706 }
1707 if (changed) {
1708 error = kernel_lun_remove(oldlun);
1709 if (error != 0) {
1710 log_warnx("failed to remove lun %d, "
1711 "target %s, CTL lun %d",
1712 oldlun->l_lun, oldtarg->t_name,
1713 oldlun->l_ctl_lun);
1714 cumulated_error++;
1715 }
1716 lun_delete(oldlun);
1717 continue;
1718 }
1719
1720 lun_set_ctl_lun(newlun, oldlun->l_ctl_lun);
1721 }
1722 }
1723
1724 /*
1725 * Now add new targets or modify existing ones.
1726 */
1727 TAILQ_FOREACH(newtarg, &newconf->conf_targets, t_next) {
1728 oldtarg = target_find(oldconf, newtarg->t_name);
1729
1730 TAILQ_FOREACH_SAFE(newlun, &newtarg->t_luns, l_next, tmplun) {
1731 if (oldtarg != NULL) {
1732 oldlun = lun_find(oldtarg, newlun->l_lun);
1733 if (oldlun != NULL) {
1734 if (newlun->l_size != oldlun->l_size ||
1735 newlun->l_size == 0) {
1736 log_debugx("resizing lun %d, "
1737 "target %s, CTL lun %d",
1738 newlun->l_lun,
1739 newtarg->t_name,
1740 newlun->l_ctl_lun);
1741 error =
1742 kernel_lun_resize(newlun);
1743 if (error != 0) {
1744 log_warnx("failed to "
1745 "resize lun %d, "
1746 "target %s, "
1747 "CTL lun %d",
1748 newlun->l_lun,
1749 newtarg->t_name,
1750 newlun->l_lun);
1751 cumulated_error++;
1752 }
1753 }
1754 continue;
1755 }
1756 }
1757 log_debugx("adding lun %d, target %s",
1758 newlun->l_lun, newtarg->t_name);
1759 error = kernel_lun_add(newlun);
1760 if (error != 0) {
1761 log_warnx("failed to add lun %d, target %s",
1762 newlun->l_lun, newtarg->t_name);
1763 lun_delete(newlun);
1764 cumulated_error++;
1765 }
1766 }
1767 if (oldtarg == NULL)
1768 kernel_port_add(newtarg);
1769 }
1770
1771 /*
1772 * Go through the new portals, opening the sockets as neccessary.
1773 */
1774 TAILQ_FOREACH(newpg, &newconf->conf_portal_groups, pg_next) {
1775 if (newpg->pg_unassigned) {
1776 log_debugx("not listening on portal-group \"%s\", "
1777 "not assigned to any target",
1778 newpg->pg_name);
1779 continue;
1780 }
1781 TAILQ_FOREACH(newp, &newpg->pg_portals, p_next) {
1782 /*
1783 * Try to find already open portal and reuse
1784 * the listening socket. We don't care about
1785 * what portal or portal group that was, what
1786 * matters is the listening address.
1787 */
1788 TAILQ_FOREACH(oldpg, &oldconf->conf_portal_groups,
1789 pg_next) {
1790 TAILQ_FOREACH(oldp, &oldpg->pg_portals,
1791 p_next) {
1792 if (strcmp(newp->p_listen,
1793 oldp->p_listen) == 0 &&
1794 oldp->p_socket > 0) {
1795 newp->p_socket =
1796 oldp->p_socket;
1797 oldp->p_socket = 0;
1798 break;
1799 }
1800 }
1801 }
1802 if (newp->p_socket > 0) {
1803 /*
1804 * We're done with this portal.
1805 */
1806 continue;
1807 }
1808
1809#ifdef ICL_KERNEL_PROXY
1810 if (proxy_mode) {
1811 newpg->pg_conf->conf_portal_id++;
1812 newp->p_id = newpg->pg_conf->conf_portal_id;
1813 log_debugx("listening on %s, portal-group "
1814 "\"%s\", portal id %d, using ICL proxy",
1815 newp->p_listen, newpg->pg_name, newp->p_id);
1816 kernel_listen(newp->p_ai, newp->p_iser,
1817 newp->p_id);
1818 continue;
1819 }
1820#endif
1821 assert(proxy_mode == false);
1822 assert(newp->p_iser == false);
1823
1824 log_debugx("listening on %s, portal-group \"%s\"",
1825 newp->p_listen, newpg->pg_name);
1826 newp->p_socket = socket(newp->p_ai->ai_family,
1827 newp->p_ai->ai_socktype,
1828 newp->p_ai->ai_protocol);
1829 if (newp->p_socket < 0) {
1830 log_warn("socket(2) failed for %s",
1831 newp->p_listen);
1832 cumulated_error++;
1833 continue;
1834 }
1835 error = setsockopt(newp->p_socket, SOL_SOCKET,
1836 SO_REUSEADDR, &one, sizeof(one));
1837 if (error != 0) {
1838 log_warn("setsockopt(SO_REUSEADDR) failed "
1839 "for %s", newp->p_listen);
1840 close(newp->p_socket);
1841 newp->p_socket = 0;
1842 cumulated_error++;
1843 continue;
1844 }
1845 error = bind(newp->p_socket, newp->p_ai->ai_addr,
1846 newp->p_ai->ai_addrlen);
1847 if (error != 0) {
1848 log_warn("bind(2) failed for %s",
1849 newp->p_listen);
1850 close(newp->p_socket);
1851 newp->p_socket = 0;
1852 cumulated_error++;
1853 continue;
1854 }
1855 error = listen(newp->p_socket, -1);
1856 if (error != 0) {
1857 log_warn("listen(2) failed for %s",
1858 newp->p_listen);
1859 close(newp->p_socket);
1860 newp->p_socket = 0;
1861 cumulated_error++;
1862 continue;
1863 }
1864 }
1865 }
1866
1867 /*
1868 * Go through the no longer used sockets, closing them.
1869 */
1870 TAILQ_FOREACH(oldpg, &oldconf->conf_portal_groups, pg_next) {
1871 TAILQ_FOREACH(oldp, &oldpg->pg_portals, p_next) {
1872 if (oldp->p_socket <= 0)
1873 continue;
1874 log_debugx("closing socket for %s, portal-group \"%s\"",
1875 oldp->p_listen, oldpg->pg_name);
1876 close(oldp->p_socket);
1877 oldp->p_socket = 0;
1878 }
1879 }
1880
1881 /* (Re-)Register on remaining/new iSNS servers. */
1882 TAILQ_FOREACH(newns, &newconf->conf_isns, i_next) {
1883 TAILQ_FOREACH(oldns, &oldconf->conf_isns, i_next) {
1884 if (strcmp(oldns->i_addr, newns->i_addr) == 0)
1885 break;
1886 }
1887 isns_register(newns, oldns);
1888 }
1889
1890 /* Schedule iSNS update */
1891 if (!TAILQ_EMPTY(&newconf->conf_isns))
1892 set_timeout((newconf->conf_isns_period + 2) / 3, false);
1893
1894 return (cumulated_error);
1895}
1896
1897bool
1898timed_out(void)
1899{
1900
1901 return (sigalrm_received);
1902}
1903
1904static void
1905sigalrm_handler_fatal(int dummy __unused)
1906{
1907 /*
1908 * It would be easiest to just log an error and exit. We can't
1909 * do this, though, because log_errx() is not signal safe, since
1910 * it calls syslog(3). Instead, set a flag checked by pdu_send()
1911 * and pdu_receive(), to call log_errx() there. Should they fail
1912 * to notice, we'll exit here one second later.
1913 */
1914 if (sigalrm_received) {
1915 /*
1916 * Oh well. Just give up and quit.
1917 */
1918 _exit(2);
1919 }
1920
1921 sigalrm_received = true;
1922}
1923
1924static void
1925sigalrm_handler(int dummy __unused)
1926{
1927
1928 sigalrm_received = true;
1929}
1930
1931void
1932set_timeout(int timeout, int fatal)
1933{
1934 struct sigaction sa;
1935 struct itimerval itv;
1936 int error;
1937
1938 if (timeout <= 0) {
1939 log_debugx("session timeout disabled");
1940 bzero(&itv, sizeof(itv));
1941 error = setitimer(ITIMER_REAL, &itv, NULL);
1942 if (error != 0)
1943 log_err(1, "setitimer");
1944 sigalrm_received = false;
1945 return;
1946 }
1947
1948 sigalrm_received = false;
1949 bzero(&sa, sizeof(sa));
1950 if (fatal)
1951 sa.sa_handler = sigalrm_handler_fatal;
1952 else
1953 sa.sa_handler = sigalrm_handler;
1954 sigfillset(&sa.sa_mask);
1955 error = sigaction(SIGALRM, &sa, NULL);
1956 if (error != 0)
1957 log_err(1, "sigaction");
1958
1959 /*
1960 * First SIGALRM will arive after conf_timeout seconds.
1961 * If we do nothing, another one will arrive a second later.
1962 */
1963 log_debugx("setting session timeout to %d seconds", timeout);
1964 bzero(&itv, sizeof(itv));
1965 itv.it_interval.tv_sec = 1;
1966 itv.it_value.tv_sec = timeout;
1967 error = setitimer(ITIMER_REAL, &itv, NULL);
1968 if (error != 0)
1969 log_err(1, "setitimer");
1970}
1971
1972static int
1973wait_for_children(bool block)
1974{
1975 pid_t pid;
1976 int status;
1977 int num = 0;
1978
1979 for (;;) {
1980 /*
1981 * If "block" is true, wait for at least one process.
1982 */
1983 if (block && num == 0)
1984 pid = wait4(-1, &status, 0, NULL);
1985 else
1986 pid = wait4(-1, &status, WNOHANG, NULL);
1987 if (pid <= 0)
1988 break;
1989 if (WIFSIGNALED(status)) {
1990 log_warnx("child process %d terminated with signal %d",
1991 pid, WTERMSIG(status));
1992 } else if (WEXITSTATUS(status) != 0) {
1993 log_warnx("child process %d terminated with exit status %d",
1994 pid, WEXITSTATUS(status));
1995 } else {
1996 log_debugx("child process %d terminated gracefully", pid);
1997 }
1998 num++;
1999 }
2000
2001 return (num);
2002}
2003
2004static void
2005handle_connection(struct portal *portal, int fd,
2006 const struct sockaddr *client_sa, bool dont_fork)
2007{
2008 struct connection *conn;
2009 int error;
2010 pid_t pid;
2011 char host[NI_MAXHOST + 1];
2012 struct conf *conf;
2013
2014 conf = portal->p_portal_group->pg_conf;
2015
2016 if (dont_fork) {
2017 log_debugx("incoming connection; not forking due to -d flag");
2018 } else {
2019 nchildren -= wait_for_children(false);
2020 assert(nchildren >= 0);
2021
2022 while (conf->conf_maxproc > 0 && nchildren >= conf->conf_maxproc) {
2023 log_debugx("maxproc limit of %d child processes hit; "
2024 "waiting for child process to exit", conf->conf_maxproc);
2025 nchildren -= wait_for_children(true);
2026 assert(nchildren >= 0);
2027 }
2028 log_debugx("incoming connection; forking child process #%d",
2029 nchildren);
2030 nchildren++;
2031 pid = fork();
2032 if (pid < 0)
2033 log_err(1, "fork");
2034 if (pid > 0) {
2035 close(fd);
2036 return;
2037 }
2038 }
2039 pidfile_close(conf->conf_pidfh);
2040
2041 error = getnameinfo(client_sa, client_sa->sa_len,
2042 host, sizeof(host), NULL, 0, NI_NUMERICHOST);
2043 if (error != 0)
2044 log_errx(1, "getnameinfo: %s", gai_strerror(error));
2045
2046 log_debugx("accepted connection from %s; portal group \"%s\"",
2047 host, portal->p_portal_group->pg_name);
2048 log_set_peer_addr(host);
2049 setproctitle("%s", host);
2050
2051 conn = connection_new(portal, fd, host, client_sa);
2052 set_timeout(conf->conf_timeout, true);
2053 kernel_capsicate();
2054 login(conn);
2055 if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
2056 kernel_handoff(conn);
2057 log_debugx("connection handed off to the kernel");
2058 } else {
2059 assert(conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY);
2060 discovery(conn);
2061 }
2062 log_debugx("nothing more to do; exiting");
2063 exit(0);
2064}
2065
2066static int
2067fd_add(int fd, fd_set *fdset, int nfds)
2068{
2069
2070 /*
2071 * Skip sockets which we failed to bind.
2072 */
2073 if (fd <= 0)
2074 return (nfds);
2075
2076 FD_SET(fd, fdset);
2077 if (fd > nfds)
2078 nfds = fd;
2079 return (nfds);
2080}
2081
2082static void
2083main_loop(struct conf *conf, bool dont_fork)
2084{
2085 struct portal_group *pg;
2086 struct portal *portal;
2087 struct sockaddr_storage client_sa;
2088 socklen_t client_salen;
2089#ifdef ICL_KERNEL_PROXY
2090 int connection_id;
2091 int portal_id;
2092#endif
2093 fd_set fdset;
2094 int error, nfds, client_fd;
2095
2096 pidfile_write(conf->conf_pidfh);
2097
2098 for (;;) {
2099 if (sighup_received || sigterm_received || timed_out())
2100 return;
2101
2102#ifdef ICL_KERNEL_PROXY
2103 if (proxy_mode) {
2104 client_salen = sizeof(client_sa);
2105 kernel_accept(&connection_id, &portal_id,
2106 (struct sockaddr *)&client_sa, &client_salen);
2107 assert(client_salen >= client_sa.ss_len);
2108
2109 log_debugx("incoming connection, id %d, portal id %d",
2110 connection_id, portal_id);
2111 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
2112 TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
2113 if (portal->p_id == portal_id) {
2114 goto found;
2115 }
2116 }
2117 }
2118
2119 log_errx(1, "kernel returned invalid portal_id %d",
2120 portal_id);
2121
2122found:
2123 handle_connection(portal, connection_id,
2124 (struct sockaddr *)&client_sa, dont_fork);
2125 } else {
2126#endif
2127 assert(proxy_mode == false);
2128
2129 FD_ZERO(&fdset);
2130 nfds = 0;
2131 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
2132 TAILQ_FOREACH(portal, &pg->pg_portals, p_next)
2133 nfds = fd_add(portal->p_socket, &fdset, nfds);
2134 }
2135 error = select(nfds + 1, &fdset, NULL, NULL, NULL);
2136 if (error <= 0) {
2137 if (errno == EINTR)
2138 return;
2139 log_err(1, "select");
2140 }
2141 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
2142 TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
2143 if (!FD_ISSET(portal->p_socket, &fdset))
2144 continue;
2145 client_salen = sizeof(client_sa);
2146 client_fd = accept(portal->p_socket,
2147 (struct sockaddr *)&client_sa,
2148 &client_salen);
2149 if (client_fd < 0)
2150 log_err(1, "accept");
2151 assert(client_salen >= client_sa.ss_len);
2152
2153 handle_connection(portal, client_fd,
2154 (struct sockaddr *)&client_sa,
2155 dont_fork);
2156 break;
2157 }
2158 }
2159#ifdef ICL_KERNEL_PROXY
2160 }
2161#endif
2162 }
2163}
2164
2165static void
2166sighup_handler(int dummy __unused)
2167{
2168
2169 sighup_received = true;
2170}
2171
2172static void
2173sigterm_handler(int dummy __unused)
2174{
2175
2176 sigterm_received = true;
2177}
2178
2179static void
2180sigchld_handler(int dummy __unused)
2181{
2182
2183 /*
2184 * The only purpose of this handler is to make SIGCHLD
2185 * interrupt the ISCSIDWAIT ioctl(2), so we can call
2186 * wait_for_children().
2187 */
2188}
2189
2190static void
2191register_signals(void)
2192{
2193 struct sigaction sa;
2194 int error;
2195
2196 bzero(&sa, sizeof(sa));
2197 sa.sa_handler = sighup_handler;
2198 sigfillset(&sa.sa_mask);
2199 error = sigaction(SIGHUP, &sa, NULL);
2200 if (error != 0)
2201 log_err(1, "sigaction");
2202
2203 sa.sa_handler = sigterm_handler;
2204 error = sigaction(SIGTERM, &sa, NULL);
2205 if (error != 0)
2206 log_err(1, "sigaction");
2207
2208 sa.sa_handler = sigterm_handler;
2209 error = sigaction(SIGINT, &sa, NULL);
2210 if (error != 0)
2211 log_err(1, "sigaction");
2212
2213 sa.sa_handler = sigchld_handler;
2214 error = sigaction(SIGCHLD, &sa, NULL);
2215 if (error != 0)
2216 log_err(1, "sigaction");
2217}
2218
2219int
2220main(int argc, char **argv)
2221{
2222 struct conf *oldconf, *newconf, *tmpconf;
2223 struct isns *newns;
2224 const char *config_path = DEFAULT_CONFIG_PATH;
2225 int debug = 0, ch, error;
2226 bool dont_daemonize = false;
2227
2228 while ((ch = getopt(argc, argv, "df:R")) != -1) {
2229 switch (ch) {
2230 case 'd':
2231 dont_daemonize = true;
2232 debug++;
2233 break;
2234 case 'f':
2235 config_path = optarg;
2236 break;
2237 case 'R':
2238#ifndef ICL_KERNEL_PROXY
2239 log_errx(1, "ctld(8) compiled without ICL_KERNEL_PROXY "
2240 "does not support iSER protocol");
2241#endif
2242 proxy_mode = true;
2243 break;
2244 case '?':
2245 default:
2246 usage();
2247 }
2248 }
2249 argc -= optind;
2250 if (argc != 0)
2251 usage();
2252
2253 log_init(debug);
2254 kernel_init();
2255
2256 oldconf = conf_new_from_kernel();
2257 newconf = conf_new_from_file(config_path);
2258 if (newconf == NULL)
2259 log_errx(1, "configuration error; exiting");
2260 if (debug > 0) {
2261 oldconf->conf_debug = debug;
2262 newconf->conf_debug = debug;
2263 }
2264
2265 error = conf_apply(oldconf, newconf);
2266 if (error != 0)
2267 log_errx(1, "failed to apply configuration; exiting");
2268
2269 conf_delete(oldconf);
2270 oldconf = NULL;
2271
2272 register_signals();
2273
2274 if (dont_daemonize == false) {
2275 log_debugx("daemonizing");
2276 if (daemon(0, 0) == -1) {
2277 log_warn("cannot daemonize");
2278 pidfile_remove(newconf->conf_pidfh);
2279 exit(1);
2280 }
2281 }
2282
2283 /* Schedule iSNS update */
2284 if (!TAILQ_EMPTY(&newconf->conf_isns))
2285 set_timeout((newconf->conf_isns_period + 2) / 3, false);
2286
2287 for (;;) {
2288 main_loop(newconf, dont_daemonize);
2289 if (sighup_received) {
2290 sighup_received = false;
2291 log_debugx("received SIGHUP, reloading configuration");
2292 tmpconf = conf_new_from_file(config_path);
2293 if (tmpconf == NULL) {
2294 log_warnx("configuration error, "
2295 "continuing with old configuration");
2296 } else {
2297 if (debug > 0)
2298 tmpconf->conf_debug = debug;
2299 oldconf = newconf;
2300 newconf = tmpconf;
2301 error = conf_apply(oldconf, newconf);
2302 if (error != 0)
2303 log_warnx("failed to reload "
2304 "configuration");
2305 conf_delete(oldconf);
2306 oldconf = NULL;
2307 }
2308 } else if (sigterm_received) {
2309 log_debugx("exiting on signal; "
2310 "reloading empty configuration");
2311
2312 log_debugx("disabling CTL iSCSI port "
2313 "and terminating all connections");
2314
2315 oldconf = newconf;
2316 newconf = conf_new();
2317 if (debug > 0)
2318 newconf->conf_debug = debug;
2319 error = conf_apply(oldconf, newconf);
2320 if (error != 0)
2321 log_warnx("failed to apply configuration");
2322 conf_delete(oldconf);
2323 oldconf = NULL;
2324
2325 log_warnx("exiting on signal");
2326 exit(0);
2327 } else {
2328 nchildren -= wait_for_children(false);
2329 assert(nchildren >= 0);
2330 if (timed_out()) {
2331 set_timeout(0, false);
2332 TAILQ_FOREACH(newns, &newconf->conf_isns, i_next)
2333 isns_check(newns);
2334 /* Schedule iSNS update */
2335 if (!TAILQ_EMPTY(&newconf->conf_isns)) {
2336 set_timeout((newconf->conf_isns_period
2337 + 2) / 3,
2338 false);
2339 }
2340 }
2341 }
2342 }
2343 /* NOTREACHED */
2344}