]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - usr.sbin/ctld/ctld.c
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / usr.sbin / ctld / ctld.c
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  * $FreeBSD$
30  */
31
32 #include <sys/types.h>
33 #include <sys/time.h>
34 #include <sys/socket.h>
35 #include <sys/wait.h>
36 #include <netinet/in.h>
37 #include <assert.h>
38 #include <ctype.h>
39 #include <errno.h>
40 #include <netdb.h>
41 #include <signal.h>
42 #include <stdbool.h>
43 #include <stdio.h>
44 #include <stdint.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <unistd.h>
48
49 #include "ctld.h"
50
51 static volatile bool sighup_received = false;
52 static volatile bool sigterm_received = false;
53 static volatile bool sigalrm_received = false;
54
55 static int nchildren = 0;
56
57 static void
58 usage(void)
59 {
60
61         fprintf(stderr, "usage: ctld [-d][-f config-file]\n");
62         exit(1);
63 }
64
65 char *
66 checked_strdup(const char *s)
67 {
68         char *c;
69
70         c = strdup(s);
71         if (c == NULL)
72                 log_err(1, "strdup");
73         return (c);
74 }
75
76 struct conf *
77 conf_new(void)
78 {
79         struct conf *conf;
80
81         conf = calloc(1, sizeof(*conf));
82         if (conf == NULL)
83                 log_err(1, "calloc");
84         TAILQ_INIT(&conf->conf_targets);
85         TAILQ_INIT(&conf->conf_auth_groups);
86         TAILQ_INIT(&conf->conf_portal_groups);
87
88         conf->conf_debug = 0;
89         conf->conf_timeout = 60;
90         conf->conf_maxproc = 30;
91
92         return (conf);
93 }
94
95 void
96 conf_delete(struct conf *conf)
97 {
98         struct target *targ, *tmp;
99         struct auth_group *ag, *cagtmp;
100         struct portal_group *pg, *cpgtmp;
101
102         assert(conf->conf_pidfh == NULL);
103
104         TAILQ_FOREACH_SAFE(targ, &conf->conf_targets, t_next, tmp)
105                 target_delete(targ);
106         TAILQ_FOREACH_SAFE(ag, &conf->conf_auth_groups, ag_next, cagtmp)
107                 auth_group_delete(ag);
108         TAILQ_FOREACH_SAFE(pg, &conf->conf_portal_groups, pg_next, cpgtmp)
109                 portal_group_delete(pg);
110         free(conf->conf_pidfile_path);
111         free(conf);
112 }
113
114 static struct auth *
115 auth_new(struct auth_group *ag)
116 {
117         struct auth *auth;
118
119         auth = calloc(1, sizeof(*auth));
120         if (auth == NULL)
121                 log_err(1, "calloc");
122         auth->a_auth_group = ag;
123         TAILQ_INSERT_TAIL(&ag->ag_auths, auth, a_next);
124         return (auth);
125 }
126
127 static void
128 auth_delete(struct auth *auth)
129 {
130         TAILQ_REMOVE(&auth->a_auth_group->ag_auths, auth, a_next);
131
132         free(auth->a_user);
133         free(auth->a_secret);
134         free(auth->a_mutual_user);
135         free(auth->a_mutual_secret);
136         free(auth);
137 }
138
139 const struct auth *
140 auth_find(struct auth_group *ag, const char *user)
141 {
142         const struct auth *auth;
143
144         TAILQ_FOREACH(auth, &ag->ag_auths, a_next) {
145                 if (strcmp(auth->a_user, user) == 0)
146                         return (auth);
147         }
148
149         return (NULL);
150 }
151
152 struct auth_group *
153 auth_group_new(struct conf *conf, const char *name)
154 {
155         struct auth_group *ag;
156
157         if (name != NULL) {
158                 ag = auth_group_find(conf, name);
159                 if (ag != NULL) {
160                         log_warnx("duplicated auth-group \"%s\"", name);
161                         return (NULL);
162                 }
163         }
164
165         ag = calloc(1, sizeof(*ag));
166         if (ag == NULL)
167                 log_err(1, "calloc");
168         if (name != NULL)
169                 ag->ag_name = checked_strdup(name);
170         TAILQ_INIT(&ag->ag_auths);
171         ag->ag_conf = conf;
172         TAILQ_INSERT_TAIL(&conf->conf_auth_groups, ag, ag_next);
173
174         return (ag);
175 }
176
177 void
178 auth_group_delete(struct auth_group *ag)
179 {
180         struct auth *auth, *tmp;
181
182         TAILQ_REMOVE(&ag->ag_conf->conf_auth_groups, ag, ag_next);
183
184         TAILQ_FOREACH_SAFE(auth, &ag->ag_auths, a_next, tmp)
185                 auth_delete(auth);
186         free(ag->ag_name);
187         free(ag);
188 }
189
190 struct auth_group *
191 auth_group_find(struct conf *conf, const char *name)
192 {
193         struct auth_group *ag;
194
195         TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) {
196                 if (ag->ag_name != NULL && strcmp(ag->ag_name, name) == 0)
197                         return (ag);
198         }
199
200         return (NULL);
201 }
202
203 static void
204 auth_check_secret_length(struct auth *auth)
205 {
206         size_t len;
207
208         len = strlen(auth->a_secret);
209         if (len > 16) {
210                 if (auth->a_auth_group->ag_name != NULL)
211                         log_warnx("secret for user \"%s\", auth-group \"%s\", "
212                             "is too long; it should be at most 16 characters "
213                             "long", auth->a_user, auth->a_auth_group->ag_name);
214                 else
215                         log_warnx("secret for user \"%s\", target \"%s\", "
216                             "is too long; it should be at most 16 characters "
217                             "long", auth->a_user,
218                             auth->a_auth_group->ag_target->t_iqn);
219         }
220         if (len < 12) {
221                 if (auth->a_auth_group->ag_name != NULL)
222                         log_warnx("secret for user \"%s\", auth-group \"%s\", "
223                             "is too short; it should be at least 12 characters "
224                             "long", auth->a_user,
225                             auth->a_auth_group->ag_name);
226                 else
227                         log_warnx("secret for user \"%s\", target \"%s\", "
228                             "is too short; it should be at least 16 characters "
229                             "long", auth->a_user,
230                             auth->a_auth_group->ag_target->t_iqn);
231         }
232
233         if (auth->a_mutual_secret != NULL) {
234                 len = strlen(auth->a_secret);
235                 if (len > 16) {
236                         if (auth->a_auth_group->ag_name != NULL)
237                                 log_warnx("mutual secret for user \"%s\", "
238                                     "auth-group \"%s\", is too long; it should "
239                                     "be at most 16 characters long",
240                                     auth->a_user, auth->a_auth_group->ag_name);
241                         else
242                                 log_warnx("mutual secret for user \"%s\", "
243                                     "target \"%s\", is too long; it should "
244                                     "be at most 16 characters long",
245                                     auth->a_user,
246                                     auth->a_auth_group->ag_target->t_iqn);
247                 }
248                 if (len < 12) {
249                         if (auth->a_auth_group->ag_name != NULL)
250                                 log_warnx("mutual secret for user \"%s\", "
251                                     "auth-group \"%s\", is too short; it "
252                                     "should be at least 12 characters long",
253                                     auth->a_user, auth->a_auth_group->ag_name);
254                         else
255                                 log_warnx("mutual secret for user \"%s\", "
256                                     "target \"%s\", is too short; it should be "
257                                     "at least 16 characters long",
258                                     auth->a_user,
259                                     auth->a_auth_group->ag_target->t_iqn);
260                 }
261         }
262 }
263
264 const struct auth *
265 auth_new_chap(struct auth_group *ag, const char *user,
266     const char *secret)
267 {
268         struct auth *auth;
269
270         if (ag->ag_type == AG_TYPE_UNKNOWN)
271                 ag->ag_type = AG_TYPE_CHAP;
272         if (ag->ag_type != AG_TYPE_CHAP) {
273                 if (ag->ag_name != NULL)
274                         log_warnx("cannot mix \"chap\" authentication with "
275                             "other types for auth-group \"%s\"", ag->ag_name);
276                 else
277                         log_warnx("cannot mix \"chap\" authentication with "
278                             "other types for target \"%s\"",
279                             ag->ag_target->t_iqn);
280                 return (NULL);
281         }
282
283         auth = auth_new(ag);
284         auth->a_user = checked_strdup(user);
285         auth->a_secret = checked_strdup(secret);
286
287         auth_check_secret_length(auth);
288
289         return (auth);
290 }
291
292 const struct auth *
293 auth_new_chap_mutual(struct auth_group *ag, const char *user,
294     const char *secret, const char *user2, const char *secret2)
295 {
296         struct auth *auth;
297
298         if (ag->ag_type == AG_TYPE_UNKNOWN)
299                 ag->ag_type = AG_TYPE_CHAP_MUTUAL;
300         if (ag->ag_type != AG_TYPE_CHAP_MUTUAL) {
301                 if (ag->ag_name != NULL)
302                         log_warnx("cannot mix \"chap-mutual\" authentication "
303                             "with other types for auth-group \"%s\"",
304                             ag->ag_name); 
305                 else
306                         log_warnx("cannot mix \"chap-mutual\" authentication "
307                             "with other types for target \"%s\"",
308                             ag->ag_target->t_iqn);
309                 return (NULL);
310         }
311
312         auth = auth_new(ag);
313         auth->a_user = checked_strdup(user);
314         auth->a_secret = checked_strdup(secret);
315         auth->a_mutual_user = checked_strdup(user2);
316         auth->a_mutual_secret = checked_strdup(secret2);
317
318         auth_check_secret_length(auth);
319
320         return (auth);
321 }
322
323 static struct portal *
324 portal_new(struct portal_group *pg)
325 {
326         struct portal *portal;
327
328         portal = calloc(1, sizeof(*portal));
329         if (portal == NULL)
330                 log_err(1, "calloc");
331         TAILQ_INIT(&portal->p_targets);
332         portal->p_portal_group = pg;
333         TAILQ_INSERT_TAIL(&pg->pg_portals, portal, p_next);
334         return (portal);
335 }
336
337 static void
338 portal_delete(struct portal *portal)
339 {
340         TAILQ_REMOVE(&portal->p_portal_group->pg_portals, portal, p_next);
341         freeaddrinfo(portal->p_ai);
342         free(portal->p_listen);
343         free(portal);
344 }
345
346 struct portal_group *
347 portal_group_new(struct conf *conf, const char *name)
348 {
349         struct portal_group *pg;
350
351         pg = portal_group_find(conf, name);
352         if (pg != NULL) {
353                 log_warnx("duplicated portal-group \"%s\"", name);
354                 return (NULL);
355         }
356
357         pg = calloc(1, sizeof(*pg));
358         if (pg == NULL)
359                 log_err(1, "calloc");
360         pg->pg_name = checked_strdup(name);
361         TAILQ_INIT(&pg->pg_portals);
362         pg->pg_conf = conf;
363         conf->conf_last_portal_group_tag++;
364         pg->pg_tag = conf->conf_last_portal_group_tag;
365         TAILQ_INSERT_TAIL(&conf->conf_portal_groups, pg, pg_next);
366
367         return (pg);
368 }
369
370 void
371 portal_group_delete(struct portal_group *pg)
372 {
373         struct portal *portal, *tmp;
374
375         TAILQ_REMOVE(&pg->pg_conf->conf_portal_groups, pg, pg_next);
376
377         TAILQ_FOREACH_SAFE(portal, &pg->pg_portals, p_next, tmp)
378                 portal_delete(portal);
379         free(pg->pg_name);
380         free(pg);
381 }
382
383 struct portal_group *
384 portal_group_find(struct conf *conf, const char *name)
385 {
386         struct portal_group *pg;
387
388         TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
389                 if (strcmp(pg->pg_name, name) == 0)
390                         return (pg);
391         }
392
393         return (NULL);
394 }
395
396 int
397 portal_group_add_listen(struct portal_group *pg, const char *value, bool iser)
398 {
399         struct addrinfo hints;
400         struct portal *portal;
401         char *addr, *ch, *arg;
402         const char *port;
403         int error, colons = 0;
404
405 #ifndef ICL_KERNEL_PROXY
406         if (iser) {
407                 log_warnx("ctld(8) compiled without ICL_KERNEL_PROXY "
408                     "does not support iSER protocol");
409                 return (-1);
410         }
411 #endif
412
413         portal = portal_new(pg);
414         portal->p_listen = checked_strdup(value);
415         portal->p_iser = iser;
416
417         arg = portal->p_listen;
418         if (arg[0] == '\0') {
419                 log_warnx("empty listen address");
420                 free(portal->p_listen);
421                 free(portal);
422                 return (1);
423         }
424         if (arg[0] == '[') {
425                 /*
426                  * IPv6 address in square brackets, perhaps with port.
427                  */
428                 arg++;
429                 addr = strsep(&arg, "]");
430                 if (arg == NULL) {
431                         log_warnx("invalid listen address %s",
432                             portal->p_listen);
433                         free(portal->p_listen);
434                         free(portal);
435                         return (1);
436                 }
437                 if (arg[0] == '\0') {
438                         port = "3260";
439                 } else if (arg[0] == ':') {
440                         port = arg + 1;
441                 } else {
442                         log_warnx("invalid listen address %s",
443                             portal->p_listen);
444                         free(portal->p_listen);
445                         free(portal);
446                         return (1);
447                 }
448         } else {
449                 /*
450                  * Either IPv6 address without brackets - and without
451                  * a port - or IPv4 address.  Just count the colons.
452                  */
453                 for (ch = arg; *ch != '\0'; ch++) {
454                         if (*ch == ':')
455                                 colons++;
456                 }
457                 if (colons > 1) {
458                         addr = arg;
459                         port = "3260";
460                 } else {
461                         addr = strsep(&arg, ":");
462                         if (arg == NULL)
463                                 port = "3260";
464                         else
465                                 port = arg;
466                 }
467         }
468
469         memset(&hints, 0, sizeof(hints));
470         hints.ai_family = PF_UNSPEC;
471         hints.ai_socktype = SOCK_STREAM;
472         hints.ai_flags = AI_PASSIVE;
473
474         error = getaddrinfo(addr, port, &hints, &portal->p_ai);
475         if (error != 0) {
476                 log_warnx("getaddrinfo for %s failed: %s",
477                     portal->p_listen, gai_strerror(error));
478                 free(portal->p_listen);
479                 free(portal);
480                 return (1);
481         }
482
483         /*
484          * XXX: getaddrinfo(3) may return multiple addresses; we should turn
485          *      those into multiple portals.
486          */
487
488         return (0);
489 }
490
491 static bool
492 valid_hex(const char ch)
493 {
494         switch (ch) {
495         case '0':
496         case '1':
497         case '2':
498         case '3':
499         case '4':
500         case '5':
501         case '6':
502         case '7':
503         case '8':
504         case '9':
505         case 'a':
506         case 'A':
507         case 'b':
508         case 'B':
509         case 'c':
510         case 'C':
511         case 'd':
512         case 'D':
513         case 'e':
514         case 'E':
515         case 'f':
516         case 'F':
517                 return (true);
518         default:
519                 return (false);
520         }
521 }
522
523 bool
524 valid_iscsi_name(const char *name)
525 {
526         int i;
527
528         if (strlen(name) >= MAX_NAME_LEN) {
529                 log_warnx("overlong name for target \"%s\"; max length allowed "
530                     "by iSCSI specification is %d characters",
531                     name, MAX_NAME_LEN);
532                 return (false);
533         }
534
535         /*
536          * In the cases below, we don't return an error, just in case the admin
537          * was right, and we're wrong.
538          */
539         if (strncasecmp(name, "iqn.", strlen("iqn.")) == 0) {
540                 for (i = strlen("iqn."); name[i] != '\0'; i++) {
541                         /*
542                          * XXX: We should verify UTF-8 normalisation, as defined
543                          *      by 3.2.6.2: iSCSI Name Encoding.
544                          */
545                         if (isalnum(name[i]))
546                                 continue;
547                         if (name[i] == '-' || name[i] == '.' || name[i] == ':')
548                                 continue;
549                         log_warnx("invalid character \"%c\" in target name "
550                             "\"%s\"; allowed characters are letters, digits, "
551                             "'-', '.', and ':'", name[i], name);
552                         break;
553                 }
554                 /*
555                  * XXX: Check more stuff: valid date and a valid reversed domain.
556                  */
557         } else if (strncasecmp(name, "eui.", strlen("eui.")) == 0) {
558                 if (strlen(name) != strlen("eui.") + 16)
559                         log_warnx("invalid target name \"%s\"; the \"eui.\" "
560                             "should be followed by exactly 16 hexadecimal "
561                             "digits", name);
562                 for (i = strlen("eui."); name[i] != '\0'; i++) {
563                         if (!valid_hex(name[i])) {
564                                 log_warnx("invalid character \"%c\" in target "
565                                     "name \"%s\"; allowed characters are 1-9 "
566                                     "and A-F", name[i], name);
567                                 break;
568                         }
569                 }
570         } else if (strncasecmp(name, "naa.", strlen("naa.")) == 0) {
571                 if (strlen(name) > strlen("naa.") + 32)
572                         log_warnx("invalid target name \"%s\"; the \"naa.\" "
573                             "should be followed by at most 32 hexadecimal "
574                             "digits", name);
575                 for (i = strlen("naa."); name[i] != '\0'; i++) {
576                         if (!valid_hex(name[i])) {
577                                 log_warnx("invalid character \"%c\" in target "
578                                     "name \"%s\"; allowed characters are 1-9 "
579                                     "and A-F", name[i], name);
580                                 break;
581                         }
582                 }
583         } else {
584                 log_warnx("invalid target name \"%s\"; should start with "
585                     "either \".iqn\", \"eui.\", or \"naa.\"",
586                     name);
587         }
588         return (true);
589 }
590
591 struct target *
592 target_new(struct conf *conf, const char *iqn)
593 {
594         struct target *targ;
595         int i, len;
596
597         targ = target_find(conf, iqn);
598         if (targ != NULL) {
599                 log_warnx("duplicated target \"%s\"", iqn);
600                 return (NULL);
601         }
602         if (valid_iscsi_name(iqn) == false) {
603                 log_warnx("target name \"%s\" is invalid", iqn);
604                 return (NULL);
605         }
606         targ = calloc(1, sizeof(*targ));
607         if (targ == NULL)
608                 log_err(1, "calloc");
609         targ->t_iqn = checked_strdup(iqn);
610
611         /*
612          * RFC 3722 requires us to normalize the name to lowercase.
613          */
614         len = strlen(iqn);
615         for (i = 0; i < len; i++)
616                 targ->t_iqn[i] = tolower(targ->t_iqn[i]);
617
618         TAILQ_INIT(&targ->t_luns);
619         targ->t_conf = conf;
620         TAILQ_INSERT_TAIL(&conf->conf_targets, targ, t_next);
621
622         return (targ);
623 }
624
625 void
626 target_delete(struct target *targ)
627 {
628         struct lun *lun, *tmp;
629
630         TAILQ_REMOVE(&targ->t_conf->conf_targets, targ, t_next);
631
632         TAILQ_FOREACH_SAFE(lun, &targ->t_luns, l_next, tmp)
633                 lun_delete(lun);
634         free(targ->t_iqn);
635         free(targ);
636 }
637
638 struct target *
639 target_find(struct conf *conf, const char *iqn)
640 {
641         struct target *targ;
642
643         TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
644                 if (strcasecmp(targ->t_iqn, iqn) == 0)
645                         return (targ);
646         }
647
648         return (NULL);
649 }
650
651 struct lun *
652 lun_new(struct target *targ, int lun_id)
653 {
654         struct lun *lun;
655
656         lun = lun_find(targ, lun_id);
657         if (lun != NULL) {
658                 log_warnx("duplicated lun %d for target \"%s\"",
659                     lun_id, targ->t_iqn);
660                 return (NULL);
661         }
662
663         lun = calloc(1, sizeof(*lun));
664         if (lun == NULL)
665                 log_err(1, "calloc");
666         lun->l_lun = lun_id;
667         TAILQ_INIT(&lun->l_options);
668         lun->l_target = targ;
669         TAILQ_INSERT_TAIL(&targ->t_luns, lun, l_next);
670
671         return (lun);
672 }
673
674 void
675 lun_delete(struct lun *lun)
676 {
677         struct lun_option *lo, *tmp;
678
679         TAILQ_REMOVE(&lun->l_target->t_luns, lun, l_next);
680
681         TAILQ_FOREACH_SAFE(lo, &lun->l_options, lo_next, tmp)
682                 lun_option_delete(lo);
683         free(lun->l_backend);
684         free(lun->l_device_id);
685         free(lun->l_path);
686         free(lun->l_serial);
687         free(lun);
688 }
689
690 struct lun *
691 lun_find(struct target *targ, int lun_id)
692 {
693         struct lun *lun;
694
695         TAILQ_FOREACH(lun, &targ->t_luns, l_next) {
696                 if (lun->l_lun == lun_id)
697                         return (lun);
698         }
699
700         return (NULL);
701 }
702
703 void
704 lun_set_backend(struct lun *lun, const char *value)
705 {
706         free(lun->l_backend);
707         lun->l_backend = checked_strdup(value);
708 }
709
710 void
711 lun_set_blocksize(struct lun *lun, size_t value)
712 {
713
714         lun->l_blocksize = value;
715 }
716
717 void
718 lun_set_device_id(struct lun *lun, const char *value)
719 {
720         free(lun->l_device_id);
721         lun->l_device_id = checked_strdup(value);
722 }
723
724 void
725 lun_set_path(struct lun *lun, const char *value)
726 {
727         free(lun->l_path);
728         lun->l_path = checked_strdup(value);
729 }
730
731 void
732 lun_set_serial(struct lun *lun, const char *value)
733 {
734         free(lun->l_serial);
735         lun->l_serial = checked_strdup(value);
736 }
737
738 void
739 lun_set_size(struct lun *lun, size_t value)
740 {
741
742         lun->l_size = value;
743 }
744
745 void
746 lun_set_ctl_lun(struct lun *lun, uint32_t value)
747 {
748
749         lun->l_ctl_lun = value;
750 }
751
752 struct lun_option *
753 lun_option_new(struct lun *lun, const char *name, const char *value)
754 {
755         struct lun_option *lo;
756
757         lo = lun_option_find(lun, name);
758         if (lo != NULL) {
759                 log_warnx("duplicated lun option %s for lun %d, target \"%s\"",
760                     name, lun->l_lun, lun->l_target->t_iqn);
761                 return (NULL);
762         }
763
764         lo = calloc(1, sizeof(*lo));
765         if (lo == NULL)
766                 log_err(1, "calloc");
767         lo->lo_name = checked_strdup(name);
768         lo->lo_value = checked_strdup(value);
769         lo->lo_lun = lun;
770         TAILQ_INSERT_TAIL(&lun->l_options, lo, lo_next);
771
772         return (lo);
773 }
774
775 void
776 lun_option_delete(struct lun_option *lo)
777 {
778
779         TAILQ_REMOVE(&lo->lo_lun->l_options, lo, lo_next);
780
781         free(lo->lo_name);
782         free(lo->lo_value);
783         free(lo);
784 }
785
786 struct lun_option *
787 lun_option_find(struct lun *lun, const char *name)
788 {
789         struct lun_option *lo;
790
791         TAILQ_FOREACH(lo, &lun->l_options, lo_next) {
792                 if (strcmp(lo->lo_name, name) == 0)
793                         return (lo);
794         }
795
796         return (NULL);
797 }
798
799 void
800 lun_option_set(struct lun_option *lo, const char *value)
801 {
802
803         free(lo->lo_value);
804         lo->lo_value = checked_strdup(value);
805 }
806
807 static struct connection *
808 connection_new(struct portal *portal, int fd, const char *host)
809 {
810         struct connection *conn;
811
812         conn = calloc(1, sizeof(*conn));
813         if (conn == NULL)
814                 log_err(1, "calloc");
815         conn->conn_portal = portal;
816         conn->conn_socket = fd;
817         conn->conn_initiator_addr = checked_strdup(host);
818
819         /*
820          * Default values, from RFC 3720, section 12.
821          */
822         conn->conn_max_data_segment_length = 8192;
823         conn->conn_max_burst_length = 262144;
824         conn->conn_immediate_data = true;
825
826         return (conn);
827 }
828
829 #if 0
830 static void
831 conf_print(struct conf *conf)
832 {
833         struct auth_group *ag;
834         struct auth *auth;
835         struct portal_group *pg;
836         struct portal *portal;
837         struct target *targ;
838         struct lun *lun;
839         struct lun_option *lo;
840
841         TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) {
842                 fprintf(stderr, "auth-group %s {\n", ag->ag_name);
843                 TAILQ_FOREACH(auth, &ag->ag_auths, a_next)
844                         fprintf(stderr, "\t chap-mutual %s %s %s %s\n",
845                             auth->a_user, auth->a_secret,
846                             auth->a_mutual_user, auth->a_mutual_secret);
847                 fprintf(stderr, "}\n");
848         }
849         TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
850                 fprintf(stderr, "portal-group %s {\n", pg->pg_name);
851                 TAILQ_FOREACH(portal, &pg->pg_portals, p_next)
852                         fprintf(stderr, "\t listen %s\n", portal->p_listen);
853                 fprintf(stderr, "}\n");
854         }
855         TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
856                 fprintf(stderr, "target %s {\n", targ->t_iqn);
857                 if (targ->t_alias != NULL)
858                         fprintf(stderr, "\t alias %s\n", targ->t_alias);
859                 TAILQ_FOREACH(lun, &targ->t_luns, l_next) {
860                         fprintf(stderr, "\tlun %d {\n", lun->l_lun);
861                         fprintf(stderr, "\t\tpath %s\n", lun->l_path);
862                         TAILQ_FOREACH(lo, &lun->l_options, lo_next)
863                                 fprintf(stderr, "\t\toption %s %s\n",
864                                     lo->lo_name, lo->lo_value);
865                         fprintf(stderr, "\t}\n");
866                 }
867                 fprintf(stderr, "}\n");
868         }
869 }
870 #endif
871
872 int
873 conf_verify(struct conf *conf)
874 {
875         struct auth_group *ag;
876         struct portal_group *pg;
877         struct target *targ;
878         struct lun *lun, *lun2;
879         bool found_lun0;
880
881         if (conf->conf_pidfile_path == NULL)
882                 conf->conf_pidfile_path = checked_strdup(DEFAULT_PIDFILE);
883
884         TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
885                 if (targ->t_auth_group == NULL) {
886                         log_warnx("missing authentication for target \"%s\"; "
887                             "must specify either \"auth-group\", \"chap\", "
888                             "or \"chap-mutual\"", targ->t_iqn);
889                         return (1);
890                 }
891                 if (targ->t_portal_group == NULL) {
892                         targ->t_portal_group = portal_group_find(conf,
893                             "default");
894                         assert(targ->t_portal_group != NULL);
895                 }
896                 found_lun0 = false;
897                 TAILQ_FOREACH(lun, &targ->t_luns, l_next) {
898                         if (lun->l_lun == 0)
899                                 found_lun0 = true;
900                         if (lun->l_backend == NULL)
901                                 lun_set_backend(lun, "block");
902                         if (strcmp(lun->l_backend, "block") == 0 &&
903                             lun->l_path == NULL) {
904                                 log_warnx("missing path for lun %d, "
905                                     "target \"%s\"", lun->l_lun, targ->t_iqn);
906                                 return (1);
907                         }
908                         if (strcmp(lun->l_backend, "ramdisk") == 0) {
909                                 if (lun->l_size == 0) {
910                                         log_warnx("missing size for "
911                                             "ramdisk-backed lun %d, "
912                                             "target \"%s\"",
913                                             lun->l_lun, targ->t_iqn);
914                                         return (1);
915                                 }
916                                 if (lun->l_path != NULL) {
917                                         log_warnx("path must not be specified "
918                                             "for ramdisk-backed lun %d, "
919                                             "target \"%s\"",
920                                             lun->l_lun, targ->t_iqn);
921                                         return (1);
922                                 }
923                         }
924                         if (lun->l_lun < 0 || lun->l_lun > 255) {
925                                 log_warnx("invalid lun number for lun %d, "
926                                     "target \"%s\"; must be between 0 and 255",
927                                     lun->l_lun, targ->t_iqn);
928                                 return (1);
929                         }
930 #if 1 /* Should we? */
931                         TAILQ_FOREACH(lun2, &targ->t_luns, l_next) {
932                                 if (lun == lun2)
933                                         continue;
934                                 if (lun->l_path != NULL &&
935                                     lun2->l_path != NULL &&
936                                     strcmp(lun->l_path, lun2->l_path) == 0)
937                                         log_debugx("WARNING: duplicate path "
938                                             "for lun %d, target \"%s\"",
939                                             lun->l_lun, targ->t_iqn);
940                         }
941 #endif
942                         if (lun->l_blocksize == 0) {
943                                 lun_set_blocksize(lun, DEFAULT_BLOCKSIZE);
944                         } else if (lun->l_blocksize <= 0) {
945                                 log_warnx("invalid blocksize for lun %d, "
946                                     "target \"%s\"; must be larger than 0",
947                                     lun->l_lun, targ->t_iqn);
948                                 return (1);
949                         }
950                         if (lun->l_size != 0 &&
951                             lun->l_size % lun->l_blocksize != 0) {
952                                 log_warnx("invalid size for lun %d, target "
953                                     "\"%s\"; must be multiple of blocksize",
954                                     lun->l_lun, targ->t_iqn);
955                                 return (1);
956                         }
957                 }
958                 if (!found_lun0) {
959                         log_warnx("mandatory LUN 0 not configured "
960                             "for target \"%s\"", targ->t_iqn);
961                         return (1);
962                 }
963         }
964         TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
965                 assert(pg->pg_name != NULL);
966                 if (pg->pg_discovery_auth_group == NULL) {
967                         pg->pg_discovery_auth_group =
968                             auth_group_find(conf, "no-access");
969                         assert(pg->pg_discovery_auth_group != NULL);
970                 }
971
972                 TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
973                         if (targ->t_portal_group == pg)
974                                 break;
975                 }
976                 if (targ == NULL) {
977                         if (strcmp(pg->pg_name, "default") != 0)
978                                 log_warnx("portal-group \"%s\" not assigned "
979                                     "to any target", pg->pg_name);
980                         pg->pg_unassigned = true;
981                 } else
982                         pg->pg_unassigned = false;
983         }
984         TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) {
985                 if (ag->ag_name == NULL)
986                         assert(ag->ag_target != NULL);
987                 else
988                         assert(ag->ag_target == NULL);
989
990                 TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
991                         if (targ->t_auth_group == ag)
992                                 break;
993                 }
994                 if (targ == NULL && ag->ag_name != NULL &&
995                     strcmp(ag->ag_name, "no-authentication") != 0 &&
996                     strcmp(ag->ag_name, "no-access") != 0) {
997                         log_warnx("auth-group \"%s\" not assigned "
998                             "to any target", ag->ag_name);
999                 }
1000         }
1001
1002         return (0);
1003 }
1004
1005 static int
1006 conf_apply(struct conf *oldconf, struct conf *newconf)
1007 {
1008         struct target *oldtarg, *newtarg, *tmptarg;
1009         struct lun *oldlun, *newlun, *tmplun;
1010         struct portal_group *oldpg, *newpg;
1011         struct portal *oldp, *newp;
1012         pid_t otherpid;
1013         int changed, cumulated_error = 0, error;
1014 #ifndef ICL_KERNEL_PROXY
1015         int one = 1;
1016 #endif
1017
1018         if (oldconf->conf_debug != newconf->conf_debug) {
1019                 log_debugx("changing debug level to %d", newconf->conf_debug);
1020                 log_init(newconf->conf_debug);
1021         }
1022
1023         if (oldconf->conf_pidfh != NULL) {
1024                 assert(oldconf->conf_pidfile_path != NULL);
1025                 if (newconf->conf_pidfile_path != NULL &&
1026                     strcmp(oldconf->conf_pidfile_path,
1027                     newconf->conf_pidfile_path) == 0) {
1028                         newconf->conf_pidfh = oldconf->conf_pidfh;
1029                         oldconf->conf_pidfh = NULL;
1030                 } else {
1031                         log_debugx("removing pidfile %s",
1032                             oldconf->conf_pidfile_path);
1033                         pidfile_remove(oldconf->conf_pidfh);
1034                         oldconf->conf_pidfh = NULL;
1035                 }
1036         }
1037
1038         if (newconf->conf_pidfh == NULL && newconf->conf_pidfile_path != NULL) {
1039                 log_debugx("opening pidfile %s", newconf->conf_pidfile_path);
1040                 newconf->conf_pidfh =
1041                     pidfile_open(newconf->conf_pidfile_path, 0600, &otherpid);
1042                 if (newconf->conf_pidfh == NULL) {
1043                         if (errno == EEXIST)
1044                                 log_errx(1, "daemon already running, pid: %jd.",
1045                                     (intmax_t)otherpid);
1046                         log_err(1, "cannot open or create pidfile \"%s\"",
1047                             newconf->conf_pidfile_path);
1048                 }
1049         }
1050
1051         TAILQ_FOREACH_SAFE(oldtarg, &oldconf->conf_targets, t_next, tmptarg) {
1052                 /*
1053                  * First, remove any targets present in the old configuration
1054                  * and missing in the new one.
1055                  */
1056                 newtarg = target_find(newconf, oldtarg->t_iqn);
1057                 if (newtarg == NULL) {
1058                         TAILQ_FOREACH_SAFE(oldlun, &oldtarg->t_luns, l_next,
1059                             tmplun) {
1060                                 log_debugx("target %s not found in the "
1061                                     "configuration file; removing its lun %d, "
1062                                     "backed by CTL lun %d",
1063                                     oldtarg->t_iqn, oldlun->l_lun,
1064                                     oldlun->l_ctl_lun);
1065                                 error = kernel_lun_remove(oldlun);
1066                                 if (error != 0) {
1067                                         log_warnx("failed to remove lun %d, "
1068                                             "target %s, CTL lun %d",
1069                                             oldlun->l_lun, oldtarg->t_iqn,
1070                                             oldlun->l_ctl_lun);
1071                                         cumulated_error++;
1072                                 }
1073                                 lun_delete(oldlun);
1074                         }
1075                         target_delete(oldtarg);
1076                         continue;
1077                 }
1078
1079                 /*
1080                  * Second, remove any LUNs present in the old target
1081                  * and missing in the new one.
1082                  */
1083                 TAILQ_FOREACH_SAFE(oldlun, &oldtarg->t_luns, l_next, tmplun) {
1084                         newlun = lun_find(newtarg, oldlun->l_lun);
1085                         if (newlun == NULL) {
1086                                 log_debugx("lun %d, target %s, CTL lun %d "
1087                                     "not found in the configuration file; "
1088                                     "removing", oldlun->l_lun, oldtarg->t_iqn,
1089                                     oldlun->l_ctl_lun);
1090                                 error = kernel_lun_remove(oldlun);
1091                                 if (error != 0) {
1092                                         log_warnx("failed to remove lun %d, "
1093                                             "target %s, CTL lun %d",
1094                                             oldlun->l_lun, oldtarg->t_iqn,
1095                                             oldlun->l_ctl_lun);
1096                                         cumulated_error++;
1097                                 }
1098                                 lun_delete(oldlun);
1099                                 continue;
1100                         }
1101
1102                         /*
1103                          * Also remove the LUNs changed by more than size.
1104                          */
1105                         changed = 0;
1106                         assert(oldlun->l_backend != NULL);
1107                         assert(newlun->l_backend != NULL);
1108                         if (strcmp(newlun->l_backend, oldlun->l_backend) != 0) {
1109                                 log_debugx("backend for lun %d, target %s, "
1110                                     "CTL lun %d changed; removing",
1111                                     oldlun->l_lun, oldtarg->t_iqn,
1112                                     oldlun->l_ctl_lun);
1113                                 changed = 1;
1114                         }
1115                         if (oldlun->l_blocksize != newlun->l_blocksize) {
1116                                 log_debugx("blocksize for lun %d, target %s, "
1117                                     "CTL lun %d changed; removing",
1118                                     oldlun->l_lun, oldtarg->t_iqn,
1119                                     oldlun->l_ctl_lun);
1120                                 changed = 1;
1121                         }
1122                         if (newlun->l_device_id != NULL &&
1123                             (oldlun->l_device_id == NULL ||
1124                              strcmp(oldlun->l_device_id, newlun->l_device_id) !=
1125                              0)) {
1126                                 log_debugx("device-id for lun %d, target %s, "
1127                                     "CTL lun %d changed; removing",
1128                                     oldlun->l_lun, oldtarg->t_iqn,
1129                                     oldlun->l_ctl_lun);
1130                                 changed = 1;
1131                         }
1132                         if (newlun->l_path != NULL &&
1133                             (oldlun->l_path == NULL ||
1134                              strcmp(oldlun->l_path, newlun->l_path) != 0)) {
1135                                 log_debugx("path for lun %d, target %s, "
1136                                     "CTL lun %d, changed; removing",
1137                                     oldlun->l_lun, oldtarg->t_iqn,
1138                                     oldlun->l_ctl_lun);
1139                                 changed = 1;
1140                         }
1141                         if (newlun->l_serial != NULL &&
1142                             (oldlun->l_serial == NULL ||
1143                              strcmp(oldlun->l_serial, newlun->l_serial) != 0)) {
1144                                 log_debugx("serial for lun %d, target %s, "
1145                                     "CTL lun %d changed; removing",
1146                                     oldlun->l_lun, oldtarg->t_iqn,
1147                                     oldlun->l_ctl_lun);
1148                                 changed = 1;
1149                         }
1150                         if (changed) {
1151                                 error = kernel_lun_remove(oldlun);
1152                                 if (error != 0) {
1153                                         log_warnx("failed to remove lun %d, "
1154                                             "target %s, CTL lun %d",
1155                                             oldlun->l_lun, oldtarg->t_iqn,
1156                                             oldlun->l_ctl_lun);
1157                                         cumulated_error++;
1158                                 }
1159                                 lun_delete(oldlun);
1160                                 continue;
1161                         }
1162
1163                         lun_set_ctl_lun(newlun, oldlun->l_ctl_lun);
1164                 }
1165         }
1166
1167         /*
1168          * Now add new targets or modify existing ones.
1169          */
1170         TAILQ_FOREACH(newtarg, &newconf->conf_targets, t_next) {
1171                 oldtarg = target_find(oldconf, newtarg->t_iqn);
1172
1173                 TAILQ_FOREACH(newlun, &newtarg->t_luns, l_next) {
1174                         if (oldtarg != NULL) {
1175                                 oldlun = lun_find(oldtarg, newlun->l_lun);
1176                                 if (oldlun != NULL) {
1177                                         if (newlun->l_size != oldlun->l_size) {
1178                                                 log_debugx("resizing lun %d, "
1179                                                     "target %s, CTL lun %d",
1180                                                     newlun->l_lun,
1181                                                     newtarg->t_iqn,
1182                                                     newlun->l_ctl_lun);
1183                                                 error =
1184                                                     kernel_lun_resize(newlun);
1185                                                 if (error != 0) {
1186                                                         log_warnx("failed to "
1187                                                             "resize lun %d, "
1188                                                             "target %s, "
1189                                                             "CTL lun %d",
1190                                                             newlun->l_lun,
1191                                                             newtarg->t_iqn,
1192                                                             newlun->l_lun);
1193                                                         cumulated_error++;
1194                                                 }
1195                                         }
1196                                         continue;
1197                                 }
1198                         }
1199                         log_debugx("adding lun %d, target %s",
1200                             newlun->l_lun, newtarg->t_iqn);
1201                         error = kernel_lun_add(newlun);
1202                         if (error != 0) {
1203                                 log_warnx("failed to add lun %d, target %s",
1204                                     newlun->l_lun, newtarg->t_iqn);
1205                                 cumulated_error++;
1206                         }
1207                 }
1208         }
1209
1210         /*
1211          * Go through the new portals, opening the sockets as neccessary.
1212          */
1213         TAILQ_FOREACH(newpg, &newconf->conf_portal_groups, pg_next) {
1214                 if (newpg->pg_unassigned) {
1215                         log_debugx("not listening on portal-group \"%s\", "
1216                             "not assigned to any target",
1217                             newpg->pg_name);
1218                         continue;
1219                 }
1220                 TAILQ_FOREACH(newp, &newpg->pg_portals, p_next) {
1221                         /*
1222                          * Try to find already open portal and reuse
1223                          * the listening socket.  We don't care about
1224                          * what portal or portal group that was, what
1225                          * matters is the listening address.
1226                          */
1227                         TAILQ_FOREACH(oldpg, &oldconf->conf_portal_groups,
1228                             pg_next) {
1229                                 TAILQ_FOREACH(oldp, &oldpg->pg_portals,
1230                                     p_next) {
1231                                         if (strcmp(newp->p_listen,
1232                                             oldp->p_listen) == 0 &&
1233                                             oldp->p_socket > 0) {
1234                                                 newp->p_socket =
1235                                                     oldp->p_socket;
1236                                                 oldp->p_socket = 0;
1237                                                 break;
1238                                         }
1239                                 }
1240                         }
1241                         if (newp->p_socket > 0) {
1242                                 /*
1243                                  * We're done with this portal.
1244                                  */
1245                                 continue;
1246                         }
1247
1248 #ifdef ICL_KERNEL_PROXY
1249                         log_debugx("listening on %s, portal-group \"%s\" using ICL proxy",
1250                             newp->p_listen, newpg->pg_name);
1251                         kernel_listen(newp->p_ai, newp->p_iser);
1252 #else
1253                         assert(newp->p_iser == false);
1254
1255                         log_debugx("listening on %s, portal-group \"%s\"",
1256                             newp->p_listen, newpg->pg_name);
1257                         newp->p_socket = socket(newp->p_ai->ai_family,
1258                             newp->p_ai->ai_socktype,
1259                             newp->p_ai->ai_protocol);
1260                         if (newp->p_socket < 0) {
1261                                 log_warn("socket(2) failed for %s",
1262                                     newp->p_listen);
1263                                 cumulated_error++;
1264                                 continue;
1265                         }
1266                         error = setsockopt(newp->p_socket, SOL_SOCKET,
1267                             SO_REUSEADDR, &one, sizeof(one));
1268                         if (error != 0) {
1269                                 log_warn("setsockopt(SO_REUSEADDR) failed "
1270                                     "for %s", newp->p_listen);
1271                                 close(newp->p_socket);
1272                                 newp->p_socket = 0;
1273                                 cumulated_error++;
1274                                 continue;
1275                         }
1276                         error = bind(newp->p_socket, newp->p_ai->ai_addr,
1277                             newp->p_ai->ai_addrlen);
1278                         if (error != 0) {
1279                                 log_warn("bind(2) failed for %s",
1280                                     newp->p_listen);
1281                                 close(newp->p_socket);
1282                                 newp->p_socket = 0;
1283                                 cumulated_error++;
1284                                 continue;
1285                         }
1286                         error = listen(newp->p_socket, -1);
1287                         if (error != 0) {
1288                                 log_warn("listen(2) failed for %s",
1289                                     newp->p_listen);
1290                                 close(newp->p_socket);
1291                                 newp->p_socket = 0;
1292                                 cumulated_error++;
1293                                 continue;
1294                         }
1295 #endif /* !ICL_KERNEL_PROXY */
1296                 }
1297         }
1298
1299         /*
1300          * Go through the no longer used sockets, closing them.
1301          */
1302         TAILQ_FOREACH(oldpg, &oldconf->conf_portal_groups, pg_next) {
1303                 TAILQ_FOREACH(oldp, &oldpg->pg_portals, p_next) {
1304                         if (oldp->p_socket <= 0)
1305                                 continue;
1306                         log_debugx("closing socket for %s, portal-group \"%s\"",
1307                             oldp->p_listen, oldpg->pg_name);
1308                         close(oldp->p_socket);
1309                         oldp->p_socket = 0;
1310                 }
1311         }
1312
1313         return (cumulated_error);
1314 }
1315
1316 bool
1317 timed_out(void)
1318 {
1319
1320         return (sigalrm_received);
1321 }
1322
1323 static void
1324 sigalrm_handler(int dummy __unused)
1325 {
1326         /*
1327          * It would be easiest to just log an error and exit.  We can't
1328          * do this, though, because log_errx() is not signal safe, since
1329          * it calls syslog(3).  Instead, set a flag checked by pdu_send()
1330          * and pdu_receive(), to call log_errx() there.  Should they fail
1331          * to notice, we'll exit here one second later.
1332          */
1333         if (sigalrm_received) {
1334                 /*
1335                  * Oh well.  Just give up and quit.
1336                  */
1337                 _exit(2);
1338         }
1339
1340         sigalrm_received = true;
1341 }
1342
1343 static void
1344 set_timeout(const struct conf *conf)
1345 {
1346         struct sigaction sa;
1347         struct itimerval itv;
1348         int error;
1349
1350         if (conf->conf_timeout <= 0) {
1351                 log_debugx("session timeout disabled");
1352                 return;
1353         }
1354
1355         bzero(&sa, sizeof(sa));
1356         sa.sa_handler = sigalrm_handler;
1357         sigfillset(&sa.sa_mask);
1358         error = sigaction(SIGALRM, &sa, NULL);
1359         if (error != 0)
1360                 log_err(1, "sigaction");
1361
1362         /*
1363          * First SIGALRM will arive after conf_timeout seconds.
1364          * If we do nothing, another one will arrive a second later.
1365          */
1366         bzero(&itv, sizeof(itv));
1367         itv.it_interval.tv_sec = 1;
1368         itv.it_value.tv_sec = conf->conf_timeout;
1369
1370         log_debugx("setting session timeout to %d seconds",
1371             conf->conf_timeout);
1372         error = setitimer(ITIMER_REAL, &itv, NULL);
1373         if (error != 0)
1374                 log_err(1, "setitimer");
1375 }
1376
1377 static int
1378 wait_for_children(bool block)
1379 {
1380         pid_t pid;
1381         int status;
1382         int num = 0;
1383
1384         for (;;) {
1385                 /*
1386                  * If "block" is true, wait for at least one process.
1387                  */
1388                 if (block && num == 0)
1389                         pid = wait4(-1, &status, 0, NULL);
1390                 else
1391                         pid = wait4(-1, &status, WNOHANG, NULL);
1392                 if (pid <= 0)
1393                         break;
1394                 if (WIFSIGNALED(status)) {
1395                         log_warnx("child process %d terminated with signal %d",
1396                             pid, WTERMSIG(status));
1397                 } else if (WEXITSTATUS(status) != 0) {
1398                         log_warnx("child process %d terminated with exit status %d",
1399                             pid, WEXITSTATUS(status));
1400                 } else {
1401                         log_debugx("child process %d terminated gracefully", pid);
1402                 }
1403                 num++;
1404         }
1405
1406         return (num);
1407 }
1408
1409 static void
1410 handle_connection(struct portal *portal, int fd, bool dont_fork)
1411 {
1412         struct connection *conn;
1413 #ifndef ICL_KERNEL_PROXY
1414         struct sockaddr_storage ss;
1415         socklen_t sslen = sizeof(ss);
1416         int error;
1417 #endif
1418         pid_t pid;
1419         char host[NI_MAXHOST + 1];
1420         struct conf *conf;
1421
1422         conf = portal->p_portal_group->pg_conf;
1423
1424         if (dont_fork) {
1425                 log_debugx("incoming connection; not forking due to -d flag");
1426         } else {
1427                 nchildren -= wait_for_children(false);
1428                 assert(nchildren >= 0);
1429
1430                 while (conf->conf_maxproc > 0 && nchildren >= conf->conf_maxproc) {
1431                         log_debugx("maxproc limit of %d child processes hit; "
1432                             "waiting for child process to exit", conf->conf_maxproc);
1433                         nchildren -= wait_for_children(true);
1434                         assert(nchildren >= 0);
1435                 }
1436                 log_debugx("incoming connection; forking child process #%d",
1437                     nchildren);
1438                 nchildren++;
1439                 pid = fork();
1440                 if (pid < 0)
1441                         log_err(1, "fork");
1442                 if (pid > 0) {
1443                         close(fd);
1444                         return;
1445                 }
1446         }
1447         pidfile_close(conf->conf_pidfh);
1448
1449 #ifdef ICL_KERNEL_PROXY
1450         /*
1451          * XXX
1452          */
1453         log_set_peer_addr("XXX");
1454 #else
1455         error = getpeername(fd, (struct sockaddr *)&ss, &sslen);
1456         if (error != 0)
1457                 log_err(1, "getpeername");
1458         error = getnameinfo((struct sockaddr *)&ss, sslen,
1459             host, sizeof(host), NULL, 0, NI_NUMERICHOST);
1460         if (error != 0)
1461                 log_errx(1, "getaddrinfo: %s", gai_strerror(error));
1462
1463         log_debugx("accepted connection from %s; portal group \"%s\"",
1464             host, portal->p_portal_group->pg_name);
1465         log_set_peer_addr(host);
1466         setproctitle("%s", host);
1467 #endif
1468
1469         conn = connection_new(portal, fd, host);
1470         set_timeout(conf);
1471         kernel_capsicate();
1472         login(conn);
1473         if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
1474                 kernel_handoff(conn);
1475                 log_debugx("connection handed off to the kernel");
1476         } else {
1477                 assert(conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY);
1478                 discovery(conn);
1479         }
1480         log_debugx("nothing more to do; exiting");
1481         exit(0);
1482 }
1483
1484 #ifndef ICL_KERNEL_PROXY
1485 static int
1486 fd_add(int fd, fd_set *fdset, int nfds)
1487 {
1488
1489         /*
1490          * Skip sockets which we failed to bind.
1491          */
1492         if (fd <= 0)
1493                 return (nfds);
1494
1495         FD_SET(fd, fdset);
1496         if (fd > nfds)
1497                 nfds = fd;
1498         return (nfds);
1499 }
1500 #endif
1501
1502 static void
1503 main_loop(struct conf *conf, bool dont_fork)
1504 {
1505         struct portal_group *pg;
1506         struct portal *portal;
1507 #ifdef ICL_KERNEL_PROXY
1508         int connection_id;
1509 #else
1510         fd_set fdset;
1511         int error, nfds, client_fd;
1512 #endif
1513
1514         pidfile_write(conf->conf_pidfh);
1515
1516         for (;;) {
1517                 if (sighup_received || sigterm_received)
1518                         return;
1519
1520 #ifdef ICL_KERNEL_PROXY
1521                 connection_id = kernel_accept();
1522                 if (connection_id == 0)
1523                         continue;
1524
1525                 /*
1526                  * XXX: This is obviously temporary.
1527                  */
1528                 pg = TAILQ_FIRST(&conf->conf_portal_groups);
1529                 portal = TAILQ_FIRST(&pg->pg_portals);
1530
1531                 handle_connection(portal, connection_id, dont_fork);
1532 #else
1533                 FD_ZERO(&fdset);
1534                 nfds = 0;
1535                 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
1536                         TAILQ_FOREACH(portal, &pg->pg_portals, p_next)
1537                                 nfds = fd_add(portal->p_socket, &fdset, nfds);
1538                 }
1539                 error = select(nfds + 1, &fdset, NULL, NULL, NULL);
1540                 if (error <= 0) {
1541                         if (errno == EINTR)
1542                                 return;
1543                         log_err(1, "select");
1544                 }
1545                 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
1546                         TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
1547                                 if (!FD_ISSET(portal->p_socket, &fdset))
1548                                         continue;
1549                                 client_fd = accept(portal->p_socket, NULL, 0);
1550                                 if (client_fd < 0)
1551                                         log_err(1, "accept");
1552                                 handle_connection(portal, client_fd, dont_fork);
1553                                 break;
1554                         }
1555                 }
1556 #endif /* !ICL_KERNEL_PROXY */
1557         }
1558 }
1559
1560 static void
1561 sighup_handler(int dummy __unused)
1562 {
1563
1564         sighup_received = true;
1565 }
1566
1567 static void
1568 sigterm_handler(int dummy __unused)
1569 {
1570
1571         sigterm_received = true;
1572 }
1573
1574 static void
1575 register_signals(void)
1576 {
1577         struct sigaction sa;
1578         int error;
1579
1580         bzero(&sa, sizeof(sa));
1581         sa.sa_handler = sighup_handler;
1582         sigfillset(&sa.sa_mask);
1583         error = sigaction(SIGHUP, &sa, NULL);
1584         if (error != 0)
1585                 log_err(1, "sigaction");
1586
1587         sa.sa_handler = sigterm_handler;
1588         error = sigaction(SIGTERM, &sa, NULL);
1589         if (error != 0)
1590                 log_err(1, "sigaction");
1591
1592         sa.sa_handler = sigterm_handler;
1593         error = sigaction(SIGINT, &sa, NULL);
1594         if (error != 0)
1595                 log_err(1, "sigaction");
1596 }
1597
1598 int
1599 main(int argc, char **argv)
1600 {
1601         struct conf *oldconf, *newconf, *tmpconf;
1602         const char *config_path = DEFAULT_CONFIG_PATH;
1603         int debug = 0, ch, error;
1604         bool dont_daemonize = false;
1605
1606         while ((ch = getopt(argc, argv, "df:")) != -1) {
1607                 switch (ch) {
1608                 case 'd':
1609                         dont_daemonize = true;
1610                         debug++;
1611                         break;
1612                 case 'f':
1613                         config_path = optarg;
1614                         break;
1615                 case '?':
1616                 default:
1617                         usage();
1618                 }
1619         }
1620         argc -= optind;
1621         if (argc != 0)
1622                 usage();
1623
1624         log_init(debug);
1625         kernel_init();
1626
1627         oldconf = conf_new_from_kernel();
1628         newconf = conf_new_from_file(config_path);
1629         if (newconf == NULL)
1630                 log_errx(1, "configuration error, exiting");
1631         if (debug > 0) {
1632                 oldconf->conf_debug = debug;
1633                 newconf->conf_debug = debug;
1634         }
1635
1636         if (dont_daemonize == false) {
1637                 if (daemon(0, 0) == -1) {
1638                         log_warn("cannot daemonize");
1639                         pidfile_remove(newconf->conf_pidfh);
1640                         exit(1);
1641                 }
1642         }
1643
1644 #ifdef ICL_KERNEL_PROXY
1645         log_debugx("enabling CTL iSCSI port");
1646         error = kernel_port_on();
1647         if (error != 0)
1648                 log_errx(1, "failed to enable CTL iSCSI port, exiting");
1649 #endif
1650
1651         error = conf_apply(oldconf, newconf);
1652         if (error != 0)
1653                 log_errx(1, "failed to apply configuration, exiting");
1654         conf_delete(oldconf);
1655         oldconf = NULL;
1656
1657         register_signals();
1658
1659 #ifndef ICL_KERNEL_PROXY
1660         log_debugx("enabling CTL iSCSI port");
1661         error = kernel_port_on();
1662         if (error != 0)
1663                 log_errx(1, "failed to enable CTL iSCSI port, exiting");
1664 #endif
1665
1666         for (;;) {
1667                 main_loop(newconf, dont_daemonize);
1668                 if (sighup_received) {
1669                         sighup_received = false;
1670                         log_debugx("received SIGHUP, reloading configuration");
1671                         tmpconf = conf_new_from_file(config_path);
1672                         if (tmpconf == NULL) {
1673                                 log_warnx("configuration error, "
1674                                     "continuing with old configuration");
1675                         } else {
1676                                 if (debug > 0)
1677                                         tmpconf->conf_debug = debug;
1678                                 oldconf = newconf;
1679                                 newconf = tmpconf;
1680                                 error = conf_apply(oldconf, newconf);
1681                                 if (error != 0)
1682                                         log_warnx("failed to reload "
1683                                             "configuration");
1684                                 conf_delete(oldconf);
1685                                 oldconf = NULL;
1686                         }
1687                 } else if (sigterm_received) {
1688                         log_debugx("exiting on signal; "
1689                             "reloading empty configuration");
1690
1691                         log_debugx("disabling CTL iSCSI port "
1692                             "and terminating all connections");
1693                         error = kernel_port_off();
1694                         if (error != 0)
1695                                 log_warnx("failed to disable CTL iSCSI port");
1696
1697                         oldconf = newconf;
1698                         newconf = conf_new();
1699                         if (debug > 0)
1700                                 newconf->conf_debug = debug;
1701                         error = conf_apply(oldconf, newconf);
1702                         if (error != 0)
1703                                 log_warnx("failed to apply configuration");
1704
1705                         log_warnx("exiting on signal");
1706                         exit(0);
1707                 } else {
1708                         nchildren -= wait_for_children(false);
1709                         assert(nchildren >= 0);
1710                 }
1711         }
1712         /* NOTREACHED */
1713 }