ctld.c revision 263717
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: stable/10/usr.sbin/ctld/ctld.c 263717 2014-03-25 11:53:47Z trasz $ 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 51static volatile bool sighup_received = false; 52static volatile bool sigterm_received = false; 53static volatile bool sigalrm_received = false; 54 55static int nchildren = 0; 56 57static void 58usage(void) 59{ 60 61 fprintf(stderr, "usage: ctld [-d][-f config-file]\n"); 62 exit(1); 63} 64 65char * 66checked_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 76struct conf * 77conf_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 95void 96conf_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 114static struct auth * 115auth_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 127static void 128auth_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 139const struct auth * 140auth_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 152struct auth_group * 153auth_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 177void 178auth_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 190struct auth_group * 191auth_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 203static void 204auth_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 264const struct auth * 265auth_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 292const struct auth * 293auth_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 323static struct portal * 324portal_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 337static void 338portal_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 346struct portal_group * 347portal_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 370void 371portal_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 383struct portal_group * 384portal_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 396int 397portal_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 491static bool 492valid_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 523bool 524valid_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 591struct target * 592target_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 625void 626target_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 638struct target * 639target_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 651struct lun * 652lun_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 674void 675lun_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 690struct lun * 691lun_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 703void 704lun_set_backend(struct lun *lun, const char *value) 705{ 706 free(lun->l_backend); 707 lun->l_backend = checked_strdup(value); 708} 709 710void 711lun_set_blocksize(struct lun *lun, size_t value) 712{ 713 714 lun->l_blocksize = value; 715} 716 717void 718lun_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 724void 725lun_set_path(struct lun *lun, const char *value) 726{ 727 free(lun->l_path); 728 lun->l_path = checked_strdup(value); 729} 730 731void 732lun_set_serial(struct lun *lun, const char *value) 733{ 734 free(lun->l_serial); 735 lun->l_serial = checked_strdup(value); 736} 737 738void 739lun_set_size(struct lun *lun, size_t value) 740{ 741 742 lun->l_size = value; 743} 744 745void 746lun_set_ctl_lun(struct lun *lun, uint32_t value) 747{ 748 749 lun->l_ctl_lun = value; 750} 751 752struct lun_option * 753lun_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 775void 776lun_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 786struct lun_option * 787lun_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 799void 800lun_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 807static struct connection * 808connection_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 830static void 831conf_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 872static int 873conf_verify_lun(struct lun *lun) 874{ 875 const struct lun *lun2; 876 877 if (lun->l_backend == NULL) 878 lun_set_backend(lun, "block"); 879 if (strcmp(lun->l_backend, "block") == 0) { 880 if (lun->l_path == NULL) { 881 log_warnx("missing path for lun %d, target \"%s\"", 882 lun->l_lun, lun->l_target->t_iqn); 883 return (1); 884 } 885 } else if (strcmp(lun->l_backend, "ramdisk") == 0) { 886 if (lun->l_size == 0) { 887 log_warnx("missing size for ramdisk-backed lun %d, " 888 "target \"%s\"", lun->l_lun, lun->l_target->t_iqn); 889 return (1); 890 } 891 if (lun->l_path != NULL) { 892 log_warnx("path must not be specified " 893 "for ramdisk-backed lun %d, target \"%s\"", 894 lun->l_lun, lun->l_target->t_iqn); 895 return (1); 896 } 897 } 898 if (lun->l_lun < 0 || lun->l_lun > 255) { 899 log_warnx("invalid lun number for lun %d, target \"%s\"; " 900 "must be between 0 and 255", lun->l_lun, 901 lun->l_target->t_iqn); 902 return (1); 903 } 904#if 1 /* Should we? */ 905 TAILQ_FOREACH(lun2, &lun->l_target->t_luns, l_next) { 906 if (lun == lun2) 907 continue; 908 if (lun->l_path != NULL && lun2->l_path != NULL && 909 strcmp(lun->l_path, lun2->l_path) == 0) 910 log_debugx("WARNING: duplicate path for lun %d, " 911 "target \"%s\"", lun->l_lun, lun->l_target->t_iqn); 912 } 913#endif 914 if (lun->l_blocksize == 0) { 915 lun_set_blocksize(lun, DEFAULT_BLOCKSIZE); 916 } else if (lun->l_blocksize < 0) { 917 log_warnx("invalid blocksize for lun %d, target \"%s\"; " 918 "must be larger than 0", lun->l_lun, lun->l_target->t_iqn); 919 return (1); 920 } 921 if (lun->l_size != 0 && lun->l_size % lun->l_blocksize != 0) { 922 log_warnx("invalid size for lun %d, target \"%s\"; " 923 "must be multiple of blocksize", lun->l_lun, 924 lun->l_target->t_iqn); 925 return (1); 926 } 927 928 return (0); 929} 930 931int 932conf_verify(struct conf *conf) 933{ 934 struct auth_group *ag; 935 struct portal_group *pg; 936 struct target *targ; 937 struct lun *lun; 938 bool found_lun0; 939 int error; 940 941 if (conf->conf_pidfile_path == NULL) 942 conf->conf_pidfile_path = checked_strdup(DEFAULT_PIDFILE); 943 944 TAILQ_FOREACH(targ, &conf->conf_targets, t_next) { 945 if (targ->t_auth_group == NULL) { 946 log_warnx("missing authentication for target \"%s\"; " 947 "must specify either \"auth-group\", \"chap\", " 948 "or \"chap-mutual\"", targ->t_iqn); 949 return (1); 950 } 951 if (targ->t_portal_group == NULL) { 952 targ->t_portal_group = portal_group_find(conf, 953 "default"); 954 assert(targ->t_portal_group != NULL); 955 } 956 found_lun0 = false; 957 TAILQ_FOREACH(lun, &targ->t_luns, l_next) { 958 error = conf_verify_lun(lun); 959 if (error != 0) 960 return (error); 961 if (lun->l_lun == 0) 962 found_lun0 = true; 963 } 964 if (!found_lun0) { 965 log_warnx("mandatory LUN 0 not configured " 966 "for target \"%s\"", targ->t_iqn); 967 return (1); 968 } 969 } 970 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) { 971 assert(pg->pg_name != NULL); 972 if (pg->pg_discovery_auth_group == NULL) { 973 pg->pg_discovery_auth_group = 974 auth_group_find(conf, "no-access"); 975 assert(pg->pg_discovery_auth_group != NULL); 976 } 977 978 TAILQ_FOREACH(targ, &conf->conf_targets, t_next) { 979 if (targ->t_portal_group == pg) 980 break; 981 } 982 if (targ == NULL) { 983 if (strcmp(pg->pg_name, "default") != 0) 984 log_warnx("portal-group \"%s\" not assigned " 985 "to any target", pg->pg_name); 986 pg->pg_unassigned = true; 987 } else 988 pg->pg_unassigned = false; 989 } 990 TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) { 991 if (ag->ag_name == NULL) 992 assert(ag->ag_target != NULL); 993 else 994 assert(ag->ag_target == NULL); 995 996 TAILQ_FOREACH(targ, &conf->conf_targets, t_next) { 997 if (targ->t_auth_group == ag) 998 break; 999 } 1000 if (targ == NULL && ag->ag_name != NULL && 1001 strcmp(ag->ag_name, "no-authentication") != 0 && 1002 strcmp(ag->ag_name, "no-access") != 0) { 1003 log_warnx("auth-group \"%s\" not assigned " 1004 "to any target", ag->ag_name); 1005 } 1006 } 1007 1008 return (0); 1009} 1010 1011static int 1012conf_apply(struct conf *oldconf, struct conf *newconf) 1013{ 1014 struct target *oldtarg, *newtarg, *tmptarg; 1015 struct lun *oldlun, *newlun, *tmplun; 1016 struct portal_group *oldpg, *newpg; 1017 struct portal *oldp, *newp; 1018 pid_t otherpid; 1019 int changed, cumulated_error = 0, error; 1020#ifndef ICL_KERNEL_PROXY 1021 int one = 1; 1022#endif 1023 1024 if (oldconf->conf_debug != newconf->conf_debug) { 1025 log_debugx("changing debug level to %d", newconf->conf_debug); 1026 log_init(newconf->conf_debug); 1027 } 1028 1029 if (oldconf->conf_pidfh != NULL) { 1030 assert(oldconf->conf_pidfile_path != NULL); 1031 if (newconf->conf_pidfile_path != NULL && 1032 strcmp(oldconf->conf_pidfile_path, 1033 newconf->conf_pidfile_path) == 0) { 1034 newconf->conf_pidfh = oldconf->conf_pidfh; 1035 oldconf->conf_pidfh = NULL; 1036 } else { 1037 log_debugx("removing pidfile %s", 1038 oldconf->conf_pidfile_path); 1039 pidfile_remove(oldconf->conf_pidfh); 1040 oldconf->conf_pidfh = NULL; 1041 } 1042 } 1043 1044 if (newconf->conf_pidfh == NULL && newconf->conf_pidfile_path != NULL) { 1045 log_debugx("opening pidfile %s", newconf->conf_pidfile_path); 1046 newconf->conf_pidfh = 1047 pidfile_open(newconf->conf_pidfile_path, 0600, &otherpid); 1048 if (newconf->conf_pidfh == NULL) { 1049 if (errno == EEXIST) 1050 log_errx(1, "daemon already running, pid: %jd.", 1051 (intmax_t)otherpid); 1052 log_err(1, "cannot open or create pidfile \"%s\"", 1053 newconf->conf_pidfile_path); 1054 } 1055 } 1056 1057 TAILQ_FOREACH_SAFE(oldtarg, &oldconf->conf_targets, t_next, tmptarg) { 1058 /* 1059 * First, remove any targets present in the old configuration 1060 * and missing in the new one. 1061 */ 1062 newtarg = target_find(newconf, oldtarg->t_iqn); 1063 if (newtarg == NULL) { 1064 TAILQ_FOREACH_SAFE(oldlun, &oldtarg->t_luns, l_next, 1065 tmplun) { 1066 log_debugx("target %s not found in new " 1067 "configuration; removing its lun %d, " 1068 "backed by CTL lun %d", 1069 oldtarg->t_iqn, oldlun->l_lun, 1070 oldlun->l_ctl_lun); 1071 error = kernel_lun_remove(oldlun); 1072 if (error != 0) { 1073 log_warnx("failed to remove lun %d, " 1074 "target %s, CTL lun %d", 1075 oldlun->l_lun, oldtarg->t_iqn, 1076 oldlun->l_ctl_lun); 1077 cumulated_error++; 1078 } 1079 lun_delete(oldlun); 1080 } 1081 target_delete(oldtarg); 1082 continue; 1083 } 1084 1085 /* 1086 * Second, remove any LUNs present in the old target 1087 * and missing in the new one. 1088 */ 1089 TAILQ_FOREACH_SAFE(oldlun, &oldtarg->t_luns, l_next, tmplun) { 1090 newlun = lun_find(newtarg, oldlun->l_lun); 1091 if (newlun == NULL) { 1092 log_debugx("lun %d, target %s, CTL lun %d " 1093 "not found in new configuration; " 1094 "removing", oldlun->l_lun, oldtarg->t_iqn, 1095 oldlun->l_ctl_lun); 1096 error = kernel_lun_remove(oldlun); 1097 if (error != 0) { 1098 log_warnx("failed to remove lun %d, " 1099 "target %s, CTL lun %d", 1100 oldlun->l_lun, oldtarg->t_iqn, 1101 oldlun->l_ctl_lun); 1102 cumulated_error++; 1103 } 1104 lun_delete(oldlun); 1105 continue; 1106 } 1107 1108 /* 1109 * Also remove the LUNs changed by more than size. 1110 */ 1111 changed = 0; 1112 assert(oldlun->l_backend != NULL); 1113 assert(newlun->l_backend != NULL); 1114 if (strcmp(newlun->l_backend, oldlun->l_backend) != 0) { 1115 log_debugx("backend for lun %d, target %s, " 1116 "CTL lun %d changed; removing", 1117 oldlun->l_lun, oldtarg->t_iqn, 1118 oldlun->l_ctl_lun); 1119 changed = 1; 1120 } 1121 if (oldlun->l_blocksize != newlun->l_blocksize) { 1122 log_debugx("blocksize for lun %d, target %s, " 1123 "CTL lun %d changed; removing", 1124 oldlun->l_lun, oldtarg->t_iqn, 1125 oldlun->l_ctl_lun); 1126 changed = 1; 1127 } 1128 if (newlun->l_device_id != NULL && 1129 (oldlun->l_device_id == NULL || 1130 strcmp(oldlun->l_device_id, newlun->l_device_id) != 1131 0)) { 1132 log_debugx("device-id for lun %d, target %s, " 1133 "CTL lun %d changed; removing", 1134 oldlun->l_lun, oldtarg->t_iqn, 1135 oldlun->l_ctl_lun); 1136 changed = 1; 1137 } 1138 if (newlun->l_path != NULL && 1139 (oldlun->l_path == NULL || 1140 strcmp(oldlun->l_path, newlun->l_path) != 0)) { 1141 log_debugx("path for lun %d, target %s, " 1142 "CTL lun %d, changed; removing", 1143 oldlun->l_lun, oldtarg->t_iqn, 1144 oldlun->l_ctl_lun); 1145 changed = 1; 1146 } 1147 if (newlun->l_serial != NULL && 1148 (oldlun->l_serial == NULL || 1149 strcmp(oldlun->l_serial, newlun->l_serial) != 0)) { 1150 log_debugx("serial for lun %d, target %s, " 1151 "CTL lun %d changed; removing", 1152 oldlun->l_lun, oldtarg->t_iqn, 1153 oldlun->l_ctl_lun); 1154 changed = 1; 1155 } 1156 if (changed) { 1157 error = kernel_lun_remove(oldlun); 1158 if (error != 0) { 1159 log_warnx("failed to remove lun %d, " 1160 "target %s, CTL lun %d", 1161 oldlun->l_lun, oldtarg->t_iqn, 1162 oldlun->l_ctl_lun); 1163 cumulated_error++; 1164 } 1165 lun_delete(oldlun); 1166 continue; 1167 } 1168 1169 lun_set_ctl_lun(newlun, oldlun->l_ctl_lun); 1170 } 1171 } 1172 1173 /* 1174 * Now add new targets or modify existing ones. 1175 */ 1176 TAILQ_FOREACH(newtarg, &newconf->conf_targets, t_next) { 1177 oldtarg = target_find(oldconf, newtarg->t_iqn); 1178 1179 TAILQ_FOREACH(newlun, &newtarg->t_luns, l_next) { 1180 if (oldtarg != NULL) { 1181 oldlun = lun_find(oldtarg, newlun->l_lun); 1182 if (oldlun != NULL) { 1183 if (newlun->l_size != oldlun->l_size) { 1184 log_debugx("resizing lun %d, " 1185 "target %s, CTL lun %d", 1186 newlun->l_lun, 1187 newtarg->t_iqn, 1188 newlun->l_ctl_lun); 1189 error = 1190 kernel_lun_resize(newlun); 1191 if (error != 0) { 1192 log_warnx("failed to " 1193 "resize lun %d, " 1194 "target %s, " 1195 "CTL lun %d", 1196 newlun->l_lun, 1197 newtarg->t_iqn, 1198 newlun->l_lun); 1199 cumulated_error++; 1200 } 1201 } 1202 continue; 1203 } 1204 } 1205 log_debugx("adding lun %d, target %s", 1206 newlun->l_lun, newtarg->t_iqn); 1207 error = kernel_lun_add(newlun); 1208 if (error != 0) { 1209 log_warnx("failed to add lun %d, target %s", 1210 newlun->l_lun, newtarg->t_iqn); 1211 cumulated_error++; 1212 } 1213 } 1214 } 1215 1216 /* 1217 * Go through the new portals, opening the sockets as neccessary. 1218 */ 1219 TAILQ_FOREACH(newpg, &newconf->conf_portal_groups, pg_next) { 1220 if (newpg->pg_unassigned) { 1221 log_debugx("not listening on portal-group \"%s\", " 1222 "not assigned to any target", 1223 newpg->pg_name); 1224 continue; 1225 } 1226 TAILQ_FOREACH(newp, &newpg->pg_portals, p_next) { 1227 /* 1228 * Try to find already open portal and reuse 1229 * the listening socket. We don't care about 1230 * what portal or portal group that was, what 1231 * matters is the listening address. 1232 */ 1233 TAILQ_FOREACH(oldpg, &oldconf->conf_portal_groups, 1234 pg_next) { 1235 TAILQ_FOREACH(oldp, &oldpg->pg_portals, 1236 p_next) { 1237 if (strcmp(newp->p_listen, 1238 oldp->p_listen) == 0 && 1239 oldp->p_socket > 0) { 1240 newp->p_socket = 1241 oldp->p_socket; 1242 oldp->p_socket = 0; 1243 break; 1244 } 1245 } 1246 } 1247 if (newp->p_socket > 0) { 1248 /* 1249 * We're done with this portal. 1250 */ 1251 continue; 1252 } 1253 1254#ifdef ICL_KERNEL_PROXY 1255 log_debugx("listening on %s, portal-group \"%s\" using ICL proxy", 1256 newp->p_listen, newpg->pg_name); 1257 kernel_listen(newp->p_ai, newp->p_iser); 1258#else 1259 assert(newp->p_iser == false); 1260 1261 log_debugx("listening on %s, portal-group \"%s\"", 1262 newp->p_listen, newpg->pg_name); 1263 newp->p_socket = socket(newp->p_ai->ai_family, 1264 newp->p_ai->ai_socktype, 1265 newp->p_ai->ai_protocol); 1266 if (newp->p_socket < 0) { 1267 log_warn("socket(2) failed for %s", 1268 newp->p_listen); 1269 cumulated_error++; 1270 continue; 1271 } 1272 error = setsockopt(newp->p_socket, SOL_SOCKET, 1273 SO_REUSEADDR, &one, sizeof(one)); 1274 if (error != 0) { 1275 log_warn("setsockopt(SO_REUSEADDR) failed " 1276 "for %s", newp->p_listen); 1277 close(newp->p_socket); 1278 newp->p_socket = 0; 1279 cumulated_error++; 1280 continue; 1281 } 1282 error = bind(newp->p_socket, newp->p_ai->ai_addr, 1283 newp->p_ai->ai_addrlen); 1284 if (error != 0) { 1285 log_warn("bind(2) failed for %s", 1286 newp->p_listen); 1287 close(newp->p_socket); 1288 newp->p_socket = 0; 1289 cumulated_error++; 1290 continue; 1291 } 1292 error = listen(newp->p_socket, -1); 1293 if (error != 0) { 1294 log_warn("listen(2) failed for %s", 1295 newp->p_listen); 1296 close(newp->p_socket); 1297 newp->p_socket = 0; 1298 cumulated_error++; 1299 continue; 1300 } 1301#endif /* !ICL_KERNEL_PROXY */ 1302 } 1303 } 1304 1305 /* 1306 * Go through the no longer used sockets, closing them. 1307 */ 1308 TAILQ_FOREACH(oldpg, &oldconf->conf_portal_groups, pg_next) { 1309 TAILQ_FOREACH(oldp, &oldpg->pg_portals, p_next) { 1310 if (oldp->p_socket <= 0) 1311 continue; 1312 log_debugx("closing socket for %s, portal-group \"%s\"", 1313 oldp->p_listen, oldpg->pg_name); 1314 close(oldp->p_socket); 1315 oldp->p_socket = 0; 1316 } 1317 } 1318 1319 return (cumulated_error); 1320} 1321 1322bool 1323timed_out(void) 1324{ 1325 1326 return (sigalrm_received); 1327} 1328 1329static void 1330sigalrm_handler(int dummy __unused) 1331{ 1332 /* 1333 * It would be easiest to just log an error and exit. We can't 1334 * do this, though, because log_errx() is not signal safe, since 1335 * it calls syslog(3). Instead, set a flag checked by pdu_send() 1336 * and pdu_receive(), to call log_errx() there. Should they fail 1337 * to notice, we'll exit here one second later. 1338 */ 1339 if (sigalrm_received) { 1340 /* 1341 * Oh well. Just give up and quit. 1342 */ 1343 _exit(2); 1344 } 1345 1346 sigalrm_received = true; 1347} 1348 1349static void 1350set_timeout(const struct conf *conf) 1351{ 1352 struct sigaction sa; 1353 struct itimerval itv; 1354 int error; 1355 1356 if (conf->conf_timeout <= 0) { 1357 log_debugx("session timeout disabled"); 1358 return; 1359 } 1360 1361 bzero(&sa, sizeof(sa)); 1362 sa.sa_handler = sigalrm_handler; 1363 sigfillset(&sa.sa_mask); 1364 error = sigaction(SIGALRM, &sa, NULL); 1365 if (error != 0) 1366 log_err(1, "sigaction"); 1367 1368 /* 1369 * First SIGALRM will arive after conf_timeout seconds. 1370 * If we do nothing, another one will arrive a second later. 1371 */ 1372 bzero(&itv, sizeof(itv)); 1373 itv.it_interval.tv_sec = 1; 1374 itv.it_value.tv_sec = conf->conf_timeout; 1375 1376 log_debugx("setting session timeout to %d seconds", 1377 conf->conf_timeout); 1378 error = setitimer(ITIMER_REAL, &itv, NULL); 1379 if (error != 0) 1380 log_err(1, "setitimer"); 1381} 1382 1383static int 1384wait_for_children(bool block) 1385{ 1386 pid_t pid; 1387 int status; 1388 int num = 0; 1389 1390 for (;;) { 1391 /* 1392 * If "block" is true, wait for at least one process. 1393 */ 1394 if (block && num == 0) 1395 pid = wait4(-1, &status, 0, NULL); 1396 else 1397 pid = wait4(-1, &status, WNOHANG, NULL); 1398 if (pid <= 0) 1399 break; 1400 if (WIFSIGNALED(status)) { 1401 log_warnx("child process %d terminated with signal %d", 1402 pid, WTERMSIG(status)); 1403 } else if (WEXITSTATUS(status) != 0) { 1404 log_warnx("child process %d terminated with exit status %d", 1405 pid, WEXITSTATUS(status)); 1406 } else { 1407 log_debugx("child process %d terminated gracefully", pid); 1408 } 1409 num++; 1410 } 1411 1412 return (num); 1413} 1414 1415static void 1416handle_connection(struct portal *portal, int fd, bool dont_fork) 1417{ 1418 struct connection *conn; 1419#ifndef ICL_KERNEL_PROXY 1420 struct sockaddr_storage ss; 1421 socklen_t sslen = sizeof(ss); 1422 int error; 1423#endif 1424 pid_t pid; 1425 char host[NI_MAXHOST + 1]; 1426 struct conf *conf; 1427 1428 conf = portal->p_portal_group->pg_conf; 1429 1430 if (dont_fork) { 1431 log_debugx("incoming connection; not forking due to -d flag"); 1432 } else { 1433 nchildren -= wait_for_children(false); 1434 assert(nchildren >= 0); 1435 1436 while (conf->conf_maxproc > 0 && nchildren >= conf->conf_maxproc) { 1437 log_debugx("maxproc limit of %d child processes hit; " 1438 "waiting for child process to exit", conf->conf_maxproc); 1439 nchildren -= wait_for_children(true); 1440 assert(nchildren >= 0); 1441 } 1442 log_debugx("incoming connection; forking child process #%d", 1443 nchildren); 1444 nchildren++; 1445 pid = fork(); 1446 if (pid < 0) 1447 log_err(1, "fork"); 1448 if (pid > 0) { 1449 close(fd); 1450 return; 1451 } 1452 } 1453 pidfile_close(conf->conf_pidfh); 1454 1455#ifdef ICL_KERNEL_PROXY 1456 /* 1457 * XXX 1458 */ 1459 log_set_peer_addr("XXX"); 1460#else 1461 error = getpeername(fd, (struct sockaddr *)&ss, &sslen); 1462 if (error != 0) 1463 log_err(1, "getpeername"); 1464 error = getnameinfo((struct sockaddr *)&ss, sslen, 1465 host, sizeof(host), NULL, 0, NI_NUMERICHOST); 1466 if (error != 0) 1467 log_errx(1, "getaddrinfo: %s", gai_strerror(error)); 1468 1469 log_debugx("accepted connection from %s; portal group \"%s\"", 1470 host, portal->p_portal_group->pg_name); 1471 log_set_peer_addr(host); 1472 setproctitle("%s", host); 1473#endif 1474 1475 conn = connection_new(portal, fd, host); 1476 set_timeout(conf); 1477 kernel_capsicate(); 1478 login(conn); 1479 if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) { 1480 kernel_handoff(conn); 1481 log_debugx("connection handed off to the kernel"); 1482 } else { 1483 assert(conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY); 1484 discovery(conn); 1485 } 1486 log_debugx("nothing more to do; exiting"); 1487 exit(0); 1488} 1489 1490#ifndef ICL_KERNEL_PROXY 1491static int 1492fd_add(int fd, fd_set *fdset, int nfds) 1493{ 1494 1495 /* 1496 * Skip sockets which we failed to bind. 1497 */ 1498 if (fd <= 0) 1499 return (nfds); 1500 1501 FD_SET(fd, fdset); 1502 if (fd > nfds) 1503 nfds = fd; 1504 return (nfds); 1505} 1506#endif 1507 1508static void 1509main_loop(struct conf *conf, bool dont_fork) 1510{ 1511 struct portal_group *pg; 1512 struct portal *portal; 1513#ifdef ICL_KERNEL_PROXY 1514 int connection_id; 1515#else 1516 fd_set fdset; 1517 int error, nfds, client_fd; 1518#endif 1519 1520 pidfile_write(conf->conf_pidfh); 1521 1522 for (;;) { 1523 if (sighup_received || sigterm_received) 1524 return; 1525 1526#ifdef ICL_KERNEL_PROXY 1527 connection_id = kernel_accept(); 1528 if (connection_id == 0) 1529 continue; 1530 1531 /* 1532 * XXX: This is obviously temporary. 1533 */ 1534 pg = TAILQ_FIRST(&conf->conf_portal_groups); 1535 portal = TAILQ_FIRST(&pg->pg_portals); 1536 1537 handle_connection(portal, connection_id, dont_fork); 1538#else 1539 FD_ZERO(&fdset); 1540 nfds = 0; 1541 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) { 1542 TAILQ_FOREACH(portal, &pg->pg_portals, p_next) 1543 nfds = fd_add(portal->p_socket, &fdset, nfds); 1544 } 1545 error = select(nfds + 1, &fdset, NULL, NULL, NULL); 1546 if (error <= 0) { 1547 if (errno == EINTR) 1548 return; 1549 log_err(1, "select"); 1550 } 1551 TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) { 1552 TAILQ_FOREACH(portal, &pg->pg_portals, p_next) { 1553 if (!FD_ISSET(portal->p_socket, &fdset)) 1554 continue; 1555 client_fd = accept(portal->p_socket, NULL, 0); 1556 if (client_fd < 0) 1557 log_err(1, "accept"); 1558 handle_connection(portal, client_fd, dont_fork); 1559 break; 1560 } 1561 } 1562#endif /* !ICL_KERNEL_PROXY */ 1563 } 1564} 1565 1566static void 1567sighup_handler(int dummy __unused) 1568{ 1569 1570 sighup_received = true; 1571} 1572 1573static void 1574sigterm_handler(int dummy __unused) 1575{ 1576 1577 sigterm_received = true; 1578} 1579 1580static void 1581register_signals(void) 1582{ 1583 struct sigaction sa; 1584 int error; 1585 1586 bzero(&sa, sizeof(sa)); 1587 sa.sa_handler = sighup_handler; 1588 sigfillset(&sa.sa_mask); 1589 error = sigaction(SIGHUP, &sa, NULL); 1590 if (error != 0) 1591 log_err(1, "sigaction"); 1592 1593 sa.sa_handler = sigterm_handler; 1594 error = sigaction(SIGTERM, &sa, NULL); 1595 if (error != 0) 1596 log_err(1, "sigaction"); 1597 1598 sa.sa_handler = sigterm_handler; 1599 error = sigaction(SIGINT, &sa, NULL); 1600 if (error != 0) 1601 log_err(1, "sigaction"); 1602} 1603 1604int 1605main(int argc, char **argv) 1606{ 1607 struct conf *oldconf, *newconf, *tmpconf; 1608 const char *config_path = DEFAULT_CONFIG_PATH; 1609 int debug = 0, ch, error; 1610 bool dont_daemonize = false; 1611 1612 while ((ch = getopt(argc, argv, "df:")) != -1) { 1613 switch (ch) { 1614 case 'd': 1615 dont_daemonize = true; 1616 debug++; 1617 break; 1618 case 'f': 1619 config_path = optarg; 1620 break; 1621 case '?': 1622 default: 1623 usage(); 1624 } 1625 } 1626 argc -= optind; 1627 if (argc != 0) 1628 usage(); 1629 1630 log_init(debug); 1631 kernel_init(); 1632 1633 oldconf = conf_new_from_kernel(); 1634 newconf = conf_new_from_file(config_path); 1635 if (newconf == NULL) 1636 log_errx(1, "configuration error, exiting"); 1637 if (debug > 0) { 1638 oldconf->conf_debug = debug; 1639 newconf->conf_debug = debug; 1640 } 1641 1642 if (dont_daemonize == false) { 1643 if (daemon(0, 0) == -1) { 1644 log_warn("cannot daemonize"); 1645 pidfile_remove(newconf->conf_pidfh); 1646 exit(1); 1647 } 1648 } 1649 1650#ifdef ICL_KERNEL_PROXY 1651 log_debugx("enabling CTL iSCSI port"); 1652 error = kernel_port_on(); 1653 if (error != 0) 1654 log_errx(1, "failed to enable CTL iSCSI port, exiting"); 1655#endif 1656 1657 error = conf_apply(oldconf, newconf); 1658 if (error != 0) 1659 log_errx(1, "failed to apply configuration, exiting"); 1660 conf_delete(oldconf); 1661 oldconf = NULL; 1662 1663 register_signals(); 1664 1665#ifndef ICL_KERNEL_PROXY 1666 log_debugx("enabling CTL iSCSI port"); 1667 error = kernel_port_on(); 1668 if (error != 0) 1669 log_errx(1, "failed to enable CTL iSCSI port, exiting"); 1670#endif 1671 1672 for (;;) { 1673 main_loop(newconf, dont_daemonize); 1674 if (sighup_received) { 1675 sighup_received = false; 1676 log_debugx("received SIGHUP, reloading configuration"); 1677 tmpconf = conf_new_from_file(config_path); 1678 if (tmpconf == NULL) { 1679 log_warnx("configuration error, " 1680 "continuing with old configuration"); 1681 } else { 1682 if (debug > 0) 1683 tmpconf->conf_debug = debug; 1684 oldconf = newconf; 1685 newconf = tmpconf; 1686 error = conf_apply(oldconf, newconf); 1687 if (error != 0) 1688 log_warnx("failed to reload " 1689 "configuration"); 1690 conf_delete(oldconf); 1691 oldconf = NULL; 1692 } 1693 } else if (sigterm_received) { 1694 log_debugx("exiting on signal; " 1695 "reloading empty configuration"); 1696 1697 log_debugx("disabling CTL iSCSI port " 1698 "and terminating all connections"); 1699 error = kernel_port_off(); 1700 if (error != 0) 1701 log_warnx("failed to disable CTL iSCSI port"); 1702 1703 oldconf = newconf; 1704 newconf = conf_new(); 1705 if (debug > 0) 1706 newconf->conf_debug = debug; 1707 error = conf_apply(oldconf, newconf); 1708 if (error != 0) 1709 log_warnx("failed to apply configuration"); 1710 1711 log_warnx("exiting on signal"); 1712 exit(0); 1713 } else { 1714 nchildren -= wait_for_children(false); 1715 assert(nchildren >= 0); 1716 } 1717 } 1718 /* NOTREACHED */ 1719} 1720