1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2012 The FreeBSD Foundation 5 * 6 * This software was developed by Edward Tomasz Napierala under sponsorship 7 * from the FreeBSD Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 */ 31 32 #include <sys/types.h> 33 #include <sys/event.h> 34 #include <sys/nv.h> 35 #include <sys/time.h> 36 #include <sys/socket.h> 37 #include <sys/stat.h> 38 #include <sys/wait.h> 39 #include <netinet/in.h> 40 #include <arpa/inet.h> 41 #include <assert.h> 42 #include <ctype.h> 43 #include <errno.h> 44 #include <libnvmf.h> 45 #include <netdb.h> 46 #include <signal.h> 47 #include <stdbool.h> 48 #include <stdio.h> 49 #include <stdint.h> 50 #include <stdlib.h> 51 #include <string.h> 52 #include <unistd.h> 53 #include <cam/scsi/scsi_all.h> 54 55 #include <algorithm> 56 #include <libutil++.hh> 57 58 #include "conf.h" 59 #include "ctld.hh" 60 #include "isns.hh" 61 62 bool proxy_mode = false; 63 64 static volatile bool sighup_received = false; 65 static volatile bool sigterm_received = false; 66 static volatile bool sigalrm_received = false; 67 68 static int kqfd; 69 static int nchildren = 0; 70 71 uint32_t conf::global_genctr; 72 73 static void 74 usage(void) 75 { 76 77 fprintf(stderr, "usage: ctld [-d][-u][-f config-file]\n"); 78 fprintf(stderr, " ctld -t [-u][-f config-file]\n"); 79 exit(1); 80 } 81 82 conf::conf() 83 { 84 conf_genctr = global_genctr++; 85 } 86 87 void 88 conf::set_debug(int debug) 89 { 90 conf_debug = debug; 91 } 92 93 void 94 conf::set_isns_period(int period) 95 { 96 conf_isns_period = period; 97 } 98 99 void 100 conf::set_isns_timeout(int timeout) 101 { 102 conf_isns_timeout = timeout; 103 } 104 105 void 106 conf::set_maxproc(int maxproc) 107 { 108 conf_maxproc = maxproc; 109 } 110 111 void 112 conf::set_timeout(int timeout) 113 { 114 conf_timeout = timeout; 115 } 116 117 bool 118 conf::set_pidfile_path(std::string_view path) 119 { 120 if (!conf_pidfile_path.empty()) { 121 log_warnx("pidfile specified more than once"); 122 return (false); 123 } 124 conf_pidfile_path = path; 125 return (true); 126 } 127 128 void 129 conf::open_pidfile() 130 { 131 const char *path; 132 pid_t otherpid; 133 134 assert(!conf_pidfile_path.empty()); 135 path = conf_pidfile_path.c_str(); 136 log_debugx("opening pidfile %s", path); 137 conf_pidfile = pidfile_open(path, 0600, &otherpid); 138 if (!conf_pidfile) { 139 if (errno == EEXIST) 140 log_errx(1, "daemon already running, pid: %jd.", 141 (intmax_t)otherpid); 142 log_err(1, "cannot open or create pidfile \"%s\"", path); 143 } 144 } 145 146 void 147 conf::write_pidfile() 148 { 149 conf_pidfile.write(); 150 } 151 152 void 153 conf::close_pidfile() 154 { 155 conf_pidfile.close(); 156 } 157 158 #ifdef ICL_KERNEL_PROXY 159 int 160 conf::add_proxy_portal(portal *portal) 161 { 162 conf_proxy_portals.push_back(portal); 163 return (conf_proxy_portals.size() - 1); 164 } 165 166 portal * 167 conf::proxy_portal(int id) 168 { 169 if (id >= conf_proxy_portals.size()) 170 return (nullptr); 171 return (conf_proxy_portals[id]); 172 } 173 #endif 174 175 bool 176 auth_group::set_type(const char *str) 177 { 178 auth_type type; 179 180 if (strcmp(str, "none") == 0) { 181 type = auth_type::NO_AUTHENTICATION; 182 } else if (strcmp(str, "deny") == 0) { 183 type = auth_type::DENY; 184 } else if (strcmp(str, "chap") == 0) { 185 type = auth_type::CHAP; 186 } else if (strcmp(str, "chap-mutual") == 0) { 187 type = auth_type::CHAP_MUTUAL; 188 } else { 189 log_warnx("invalid auth-type \"%s\" for %s", str, label()); 190 return (false); 191 } 192 193 if (ag_type != auth_type::UNKNOWN && ag_type != type) { 194 log_warnx("cannot set auth-type to \"%s\" for %s; " 195 "already has a different type", str, label()); 196 return (false); 197 } 198 199 ag_type = type; 200 201 return (true); 202 } 203 204 void 205 auth_group::set_type(auth_type type) 206 { 207 assert(ag_type == auth_type::UNKNOWN); 208 209 ag_type = type; 210 } 211 212 const struct auth * 213 auth_group::find_auth(std::string_view user) const 214 { 215 auto it = ag_auths.find(std::string(user)); 216 if (it == ag_auths.end()) 217 return (nullptr); 218 219 return (&it->second); 220 } 221 222 void 223 auth_group::check_secret_length(const char *user, const char *secret, 224 const char *secret_type) 225 { 226 size_t len; 227 228 len = strlen(secret); 229 assert(len != 0); 230 if (len > 16) { 231 log_warnx("%s for user \"%s\", %s, is too long; it should be " 232 "at most 16 characters long", secret_type, user, label()); 233 } 234 if (len < 12) { 235 log_warnx("%s for user \"%s\", %s, is too short; it should be " 236 "at least 12 characters long", secret_type, user, label()); 237 } 238 } 239 240 bool 241 auth_group::add_chap(const char *user, const char *secret) 242 { 243 if (ag_type == auth_type::UNKNOWN) 244 ag_type = auth_type::CHAP; 245 if (ag_type != auth_type::CHAP) { 246 log_warnx("cannot mix \"chap\" authentication with " 247 "other types for %s", label()); 248 return (false); 249 } 250 251 check_secret_length(user, secret, "secret"); 252 253 const auto &pair = ag_auths.try_emplace(user, secret); 254 if (!pair.second) { 255 log_warnx("duplicate credentials for user \"%s\" for %s", 256 user, label()); 257 return (false); 258 } 259 260 return (true); 261 } 262 263 bool 264 auth_group::add_chap_mutual(const char *user, const char *secret, 265 const char *user2, const char *secret2) 266 { 267 if (ag_type == auth_type::UNKNOWN) 268 ag_type = auth_type::CHAP_MUTUAL; 269 if (ag_type != auth_type::CHAP_MUTUAL) { 270 log_warnx("cannot mix \"chap-mutual\" authentication " 271 "with other types for %s", label()); 272 return (false); 273 } 274 275 check_secret_length(user, secret, "secret"); 276 check_secret_length(user, secret2, "mutual secret"); 277 278 const auto &pair = ag_auths.try_emplace(user, secret, user2, secret2); 279 if (!pair.second) { 280 log_warnx("duplicate credentials for user \"%s\" for %s", 281 user, label()); 282 return (false); 283 } 284 285 return (true); 286 } 287 288 bool 289 auth_group::add_host_nqn(std::string_view nqn) 290 { 291 /* Silently ignore duplicates. */ 292 ag_host_names.emplace(nqn); 293 return (true); 294 } 295 296 bool 297 auth_group::host_permitted(std::string_view nqn) const 298 { 299 if (ag_host_names.empty()) 300 return (true); 301 302 return (ag_host_names.count(std::string(nqn)) != 0); 303 } 304 305 bool 306 auth_group::add_initiator_name(std::string_view name) 307 { 308 /* Silently ignore duplicates. */ 309 ag_initiator_names.emplace(name); 310 return (true); 311 } 312 313 bool 314 auth_group::initiator_permitted(std::string_view initiator_name) const 315 { 316 if (ag_initiator_names.empty()) 317 return (true); 318 319 return (ag_initiator_names.count(std::string(initiator_name)) != 0); 320 } 321 322 bool 323 auth_portal::parse(const char *portal) 324 { 325 std::string net(portal); 326 std::string mask; 327 328 /* Split into 'net' (address) and 'mask'. */ 329 size_t pos = net.find('/'); 330 if (pos != net.npos) { 331 mask = net.substr(pos + 1); 332 if (mask.empty()) 333 return false; 334 net.resize(pos); 335 } 336 if (net.empty()) 337 return false; 338 339 /* 340 * If 'net' starts with a '[', ensure it ends with a ']' and 341 * force interpreting the address as IPv6. 342 */ 343 bool brackets = net[0] == '['; 344 if (brackets) { 345 net.erase(0, 1); 346 347 size_t len = net.length(); 348 if (len < 2) 349 return false; 350 if (net[len - 1] != ']') 351 return false; 352 net.resize(len - 1); 353 } 354 355 /* Parse address from 'net' and set default mask. */ 356 if (brackets || net.find(':') != net.npos) { 357 struct sockaddr_in6 *sin6 = 358 (struct sockaddr_in6 *)&ap_sa; 359 360 sin6->sin6_len = sizeof(*sin6); 361 sin6->sin6_family = AF_INET6; 362 if (inet_pton(AF_INET6, net.c_str(), &sin6->sin6_addr) <= 0) 363 return false; 364 ap_mask = sizeof(sin6->sin6_addr) * 8; 365 } else { 366 struct sockaddr_in *sin = 367 (struct sockaddr_in *)&ap_sa; 368 369 sin->sin_len = sizeof(*sin); 370 sin->sin_family = AF_INET; 371 if (inet_pton(AF_INET, net.c_str(), &sin->sin_addr) <= 0) 372 return false; 373 ap_mask = sizeof(sin->sin_addr) * 8; 374 } 375 376 /* Parse explicit mask if present. */ 377 if (!mask.empty()) { 378 char *tmp; 379 long m = strtol(mask.c_str(), &tmp, 0); 380 if (m < 0 || m > ap_mask || tmp[0] != 0) 381 return false; 382 ap_mask = m; 383 } 384 385 return true; 386 } 387 388 bool 389 auth_group::add_host_address(const char *address) 390 { 391 auth_portal ap; 392 if (!ap.parse(address)) { 393 log_warnx("invalid controller address \"%s\" for %s", address, 394 label()); 395 return (false); 396 } 397 398 ag_host_addresses.emplace_back(ap); 399 return (true); 400 } 401 402 bool 403 auth_group::add_initiator_portal(const char *portal) 404 { 405 auth_portal ap; 406 if (!ap.parse(portal)) { 407 log_warnx("invalid initiator portal \"%s\" for %s", portal, 408 label()); 409 return (false); 410 } 411 412 ag_initiator_portals.emplace_back(ap); 413 return (true); 414 } 415 416 bool 417 auth_portal::matches(const struct sockaddr *sa) const 418 { 419 const uint8_t *a, *b; 420 int i; 421 422 if (ap_sa.ss_family != sa->sa_family) 423 return (false); 424 425 if (sa->sa_family == AF_INET) { 426 a = (const uint8_t *) 427 &((const struct sockaddr_in *)sa)->sin_addr; 428 b = (const uint8_t *) 429 &((const struct sockaddr_in *)&ap_sa)->sin_addr; 430 } else { 431 a = (const uint8_t *) 432 &((const struct sockaddr_in6 *)sa)->sin6_addr; 433 b = (const uint8_t *) 434 &((const struct sockaddr_in6 *)&ap_sa)->sin6_addr; 435 } 436 for (i = 0; i < ap_mask / 8; i++) { 437 if (a[i] != b[i]) 438 return (false); 439 } 440 if ((ap_mask % 8) != 0) { 441 uint8_t bmask = 0xff << (8 - (ap_mask % 8)); 442 if ((a[i] & bmask) != (b[i] & bmask)) 443 return (false); 444 } 445 return (true); 446 } 447 448 bool 449 auth_group::host_permitted(const struct sockaddr *sa) const 450 { 451 if (ag_host_addresses.empty()) 452 return (true); 453 454 for (const auth_portal &ap : ag_host_addresses) 455 if (ap.matches(sa)) 456 return (true); 457 return (false); 458 } 459 460 bool 461 auth_group::initiator_permitted(const struct sockaddr *sa) const 462 { 463 if (ag_initiator_portals.empty()) 464 return (true); 465 466 for (const auth_portal &ap : ag_initiator_portals) 467 if (ap.matches(sa)) 468 return (true); 469 return (false); 470 } 471 472 struct auth_group * 473 conf::add_auth_group(const char *name) 474 { 475 const auto &pair = conf_auth_groups.try_emplace(name, 476 std::make_shared<auth_group>(freebsd::stringf("auth-group \"%s\"", 477 name))); 478 if (!pair.second) { 479 log_warnx("duplicated auth-group \"%s\"", name); 480 return (NULL); 481 } 482 483 return (pair.first->second.get()); 484 } 485 486 /* 487 * Make it possible to redefine the default auth-group, but only once. 488 */ 489 struct auth_group * 490 conf::define_default_auth_group() 491 { 492 if (conf_default_ag_defined) { 493 log_warnx("duplicated auth-group \"default\""); 494 return (nullptr); 495 } 496 497 conf_default_ag_defined = true; 498 return (find_auth_group("default").get()); 499 } 500 501 auth_group_sp 502 conf::find_auth_group(std::string_view name) 503 { 504 auto it = conf_auth_groups.find(std::string(name)); 505 if (it == conf_auth_groups.end()) 506 return {}; 507 508 return (it->second); 509 } 510 511 portal_group::portal_group(struct conf *conf, std::string_view name) : 512 pg_conf(conf), pg_options(nvlist_create(0)), pg_name(name) 513 { 514 } 515 516 struct portal_group * 517 conf::add_portal_group(const char *name) 518 { 519 auto pair = conf_portal_groups.try_emplace(name, 520 iscsi_make_portal_group(this, name)); 521 if (!pair.second) { 522 log_warnx("duplicated portal-group \"%s\"", name); 523 return (nullptr); 524 } 525 526 return (pair.first->second.get()); 527 } 528 529 /* 530 * Make it possible to redefine the default portal-group, but only 531 * once. 532 */ 533 struct portal_group * 534 conf::define_default_portal_group() 535 { 536 if (conf_default_pg_defined) { 537 log_warnx("duplicated portal-group \"default\""); 538 return (nullptr); 539 } 540 541 conf_default_pg_defined = true; 542 return (find_portal_group("default")); 543 } 544 545 struct portal_group * 546 conf::find_portal_group(std::string_view name) 547 { 548 auto it = conf_portal_groups.find(std::string(name)); 549 if (it == conf_portal_groups.end()) 550 return (nullptr); 551 552 return (it->second.get()); 553 } 554 555 struct portal_group * 556 conf::add_transport_group(const char *name) 557 { 558 auto pair = conf_transport_groups.try_emplace(name, 559 nvmf_make_transport_group(this, name)); 560 if (!pair.second) { 561 log_warnx("duplicated transport-group \"%s\"", name); 562 return (nullptr); 563 } 564 565 return (pair.first->second.get()); 566 } 567 568 /* 569 * Make it possible to redefine the default transport-group, but only 570 * once. 571 */ 572 struct portal_group * 573 conf::define_default_transport_group() 574 { 575 if (conf_default_tg_defined) { 576 log_warnx("duplicated transport-group \"default\""); 577 return (nullptr); 578 } 579 580 conf_default_tg_defined = true; 581 return (find_transport_group("default")); 582 } 583 584 struct portal_group * 585 conf::find_transport_group(std::string_view name) 586 { 587 auto it = conf_transport_groups.find(std::string(name)); 588 if (it == conf_transport_groups.end()) 589 return (nullptr); 590 591 return (it->second.get()); 592 } 593 594 bool 595 portal_group::is_dummy() const 596 { 597 if (pg_foreign) 598 return (true); 599 if (pg_portals.empty()) 600 return (true); 601 return (false); 602 } 603 604 freebsd::addrinfo_up 605 parse_addr_port(const char *address, const char *def_port) 606 { 607 struct addrinfo hints, *ai; 608 int error; 609 610 std::string addr(address); 611 std::string port(def_port); 612 if (addr[0] == '[') { 613 /* 614 * IPv6 address in square brackets, perhaps with port. 615 */ 616 addr.erase(0, 1); 617 size_t pos = addr.find(']'); 618 if (pos == 0 || pos == addr.npos) 619 return {}; 620 if (pos < addr.length() - 1) { 621 port = addr.substr(pos + 1); 622 if (port[0] != ':' || port.length() < 2) 623 return {}; 624 port.erase(0, 1); 625 } 626 addr.resize(pos); 627 } else { 628 /* 629 * Either IPv6 address without brackets - and without 630 * a port - or IPv4 address. Just count the colons. 631 */ 632 size_t pos = addr.find(':'); 633 if (pos != addr.npos && addr.find(':', pos + 1) == addr.npos) { 634 /* Only a single colon at `pos`. */ 635 if (pos == addr.length() - 1) 636 return {}; 637 port = addr.substr(pos + 1); 638 addr.resize(pos); 639 } 640 } 641 642 memset(&hints, 0, sizeof(hints)); 643 hints.ai_family = PF_UNSPEC; 644 hints.ai_socktype = SOCK_STREAM; 645 hints.ai_flags = AI_PASSIVE; 646 error = getaddrinfo(addr.c_str(), port.c_str(), &hints, &ai); 647 if (error != 0) 648 return {}; 649 return freebsd::addrinfo_up(ai); 650 } 651 652 void 653 portal_group::add_port(struct portal_group_port *port) 654 { 655 pg_ports.emplace(port->target()->name(), port); 656 } 657 658 void 659 portal_group::remove_port(struct portal_group_port *port) 660 { 661 auto it = pg_ports.find(port->target()->name()); 662 pg_ports.erase(it); 663 } 664 665 freebsd::nvlist_up 666 portal_group::options() const 667 { 668 return (freebsd::nvlist_up(nvlist_clone(pg_options.get()))); 669 } 670 671 bool 672 portal_group::add_option(const char *name, const char *value) 673 { 674 return (option_new(pg_options.get(), name, value)); 675 } 676 677 bool 678 portal_group::set_discovery_auth_group(const char *ag_name) 679 { 680 if (pg_discovery_auth_group != nullptr) { 681 log_warnx("discovery-auth-group for %s " 682 "\"%s\" specified more than once", keyword(), name()); 683 return (false); 684 } 685 pg_discovery_auth_group = pg_conf->find_auth_group(ag_name); 686 if (pg_discovery_auth_group == nullptr) { 687 log_warnx("unknown discovery-auth-group \"%s\" " 688 "for %s \"%s\"", ag_name, keyword(), name()); 689 return (false); 690 } 691 return (true); 692 } 693 694 bool 695 portal_group::set_dscp(u_int dscp) 696 { 697 if (dscp >= 0x40) { 698 log_warnx("invalid DSCP value %u for %s \"%s\"", 699 dscp, keyword(), name()); 700 return (false); 701 } 702 703 pg_dscp = dscp; 704 return (true); 705 } 706 707 void 708 portal_group::set_foreign() 709 { 710 pg_foreign = true; 711 } 712 713 bool 714 portal_group::set_offload(const char *offload) 715 { 716 if (!pg_offload.empty()) { 717 log_warnx("cannot set offload to \"%s\" for " 718 "%s \"%s\"; already defined", 719 offload, keyword(), name()); 720 return (false); 721 } 722 723 pg_offload = offload; 724 return (true); 725 } 726 727 bool 728 portal_group::set_pcp(u_int pcp) 729 { 730 if (pcp > 7) { 731 log_warnx("invalid PCP value %u for %s \"%s\"", 732 pcp, keyword(), name()); 733 return (false); 734 } 735 736 pg_pcp = pcp; 737 return (true); 738 } 739 740 bool 741 portal_group::set_redirection(const char *addr) 742 { 743 if (!pg_redirection.empty()) { 744 log_warnx("cannot set redirection to \"%s\" for " 745 "%s \"%s\"; already defined", 746 addr, keyword(), name()); 747 return (false); 748 } 749 750 pg_redirection = addr; 751 return (true); 752 } 753 754 void 755 portal_group::set_tag(uint16_t tag) 756 { 757 pg_tag = tag; 758 } 759 760 void 761 portal_group::verify(struct conf *conf) 762 { 763 if (pg_discovery_auth_group == nullptr) { 764 pg_discovery_auth_group = conf->find_auth_group("default"); 765 assert(pg_discovery_auth_group != nullptr); 766 } 767 768 if (pg_discovery_filter == discovery_filter::UNKNOWN) 769 pg_discovery_filter = discovery_filter::NONE; 770 771 if (!pg_redirection.empty()) { 772 if (!pg_ports.empty()) { 773 log_debugx("%s \"%s\" assigned to target, " 774 "but configured for redirection", keyword(), 775 name()); 776 } 777 pg_assigned = true; 778 } else if (!pg_ports.empty()) { 779 pg_assigned = true; 780 } else { 781 if (pg_name != "default") 782 log_warnx("%s \"%s\" not assigned " 783 "to any target", keyword(), name()); 784 pg_assigned = false; 785 } 786 } 787 788 /* 789 * Try to reuse a socket for 'newp' from an existing socket in one of 790 * our portals. 791 */ 792 bool 793 portal_group::reuse_socket(struct portal &newp) 794 { 795 for (portal_up &portal : pg_portals) { 796 if (newp.reuse_socket(*portal)) 797 return (true); 798 } 799 return (false); 800 } 801 802 int 803 portal_group::open_sockets(struct conf &oldconf) 804 { 805 int cumulated_error = 0; 806 807 if (pg_foreign) 808 return (0); 809 810 if (!pg_assigned) { 811 log_debugx("not listening on %s \"%s\", " 812 "not assigned to any target", keyword(), name()); 813 return (0); 814 } 815 816 for (portal_up &portal : pg_portals) { 817 if (!portal->prepare()) { 818 cumulated_error++; 819 continue; 820 } 821 822 /* 823 * Try to find already open portal and reuse the 824 * listening socket. We don't care about what portal 825 * or portal group that was, what matters is the 826 * listening address. 827 */ 828 if (oldconf.reuse_portal_group_socket(*portal)) 829 continue; 830 831 if (!portal->init_socket()) { 832 cumulated_error++; 833 continue; 834 } 835 } 836 return (cumulated_error); 837 } 838 839 void 840 portal_group::close_sockets() 841 { 842 for (portal_up &portal : pg_portals) { 843 if (portal->socket() < 0) 844 continue; 845 log_debugx("closing socket for %s, %s \"%s\"", 846 portal->listen(), keyword(), name()); 847 portal->close(); 848 } 849 } 850 851 bool 852 conf::add_isns(const char *addr) 853 { 854 if (conf_isns.count(addr) > 0) { 855 log_warnx("duplicate iSNS address %s", addr); 856 return (false); 857 } 858 859 freebsd::addrinfo_up ai = parse_addr_port(addr, "3205"); 860 if (!ai) { 861 log_warnx("invalid iSNS address %s", addr); 862 return (false); 863 } 864 865 /* 866 * XXX: getaddrinfo(3) may return multiple addresses; we should turn 867 * those into multiple servers. 868 */ 869 870 conf_isns.emplace(addr, isns(addr, std::move(ai))); 871 return (true); 872 } 873 874 875 freebsd::fd_up 876 isns::connect() 877 { 878 freebsd::fd_up s; 879 880 s = socket(i_ai->ai_family, i_ai->ai_socktype, i_ai->ai_protocol); 881 if (!s) { 882 log_warn("socket(2) failed for %s", addr()); 883 return (s); 884 } 885 if (::connect(s, i_ai->ai_addr, i_ai->ai_addrlen)) { 886 log_warn("connect(2) failed for %s", addr()); 887 s.reset(); 888 } 889 return (s); 890 } 891 892 bool 893 isns::send_request(int s, struct isns_req req) 894 { 895 if (!req.send(s)) { 896 log_warn("send(2) failed for %s", addr()); 897 return (false); 898 } 899 if (!req.receive(s)) { 900 log_warn("receive(2) failed for %s", addr()); 901 return (false); 902 } 903 uint32_t error = req.get_status(); 904 if (error != 0) { 905 log_warnx("iSNS %s error %u for %s", req.descr(), error, 906 addr()); 907 return (false); 908 } 909 return (true); 910 } 911 912 struct isns_req 913 conf::isns_register_request(const char *hostname) 914 { 915 const struct portal_group *pg; 916 917 isns_req req(ISNS_FUNC_DEVATTRREG, ISNS_FLAG_CLIENT, "register"); 918 req.add_str(32, conf_first_target->name()); 919 req.add_delim(); 920 req.add_str(1, hostname); 921 req.add_32(2, 2); /* 2 -- iSCSI */ 922 req.add_32(6, conf_isns_period); 923 for (const auto &kv : conf_portal_groups) { 924 pg = kv.second.get(); 925 926 if (!pg->assigned()) 927 continue; 928 for (const portal_up &portal : pg->portals()) { 929 req.add_addr(16, portal->ai()); 930 req.add_port(17, portal->ai()); 931 } 932 } 933 for (const auto &kv : conf_targets) { 934 const struct target *target = kv.second.get(); 935 936 req.add_str(32, target->name()); 937 req.add_32(33, 1); /* 1 -- Target*/ 938 if (target->has_alias()) 939 req.add_str(34, target->alias()); 940 for (const port *port : target->ports()) { 941 pg = port->portal_group(); 942 if (pg == nullptr) 943 continue; 944 req.add_32(51, pg->tag()); 945 for (const portal_up &portal : pg->portals()) { 946 req.add_addr(49, portal->ai()); 947 req.add_port(50, portal->ai()); 948 } 949 } 950 } 951 return (req); 952 } 953 954 struct isns_req 955 conf::isns_check_request(const char *hostname) 956 { 957 isns_req req(ISNS_FUNC_DEVATTRQRY, ISNS_FLAG_CLIENT, "check"); 958 req.add_str(32, conf_first_target->name()); 959 req.add_str(1, hostname); 960 req.add_delim(); 961 req.add(2, 0, NULL); 962 return (req); 963 } 964 965 struct isns_req 966 conf::isns_deregister_request(const char *hostname) 967 { 968 isns_req req(ISNS_FUNC_DEVDEREG, ISNS_FLAG_CLIENT, "deregister"); 969 req.add_str(32, conf_first_target->name()); 970 req.add_delim(); 971 req.add_str(1, hostname); 972 return (req); 973 } 974 975 void 976 conf::isns_register_targets(struct isns *isns, struct conf *oldconf) 977 { 978 int error; 979 char hostname[256]; 980 981 if (conf_targets.empty() || conf_portal_groups.empty()) 982 return; 983 start_timer(conf_isns_timeout); 984 freebsd::fd_up s = isns->connect(); 985 if (!s) { 986 stop_timer(); 987 return; 988 } 989 error = gethostname(hostname, sizeof(hostname)); 990 if (error != 0) 991 log_err(1, "gethostname"); 992 993 if (oldconf == nullptr || oldconf->conf_first_target == nullptr) 994 oldconf = this; 995 isns->send_request(s, oldconf->isns_deregister_request(hostname)); 996 isns->send_request(s, isns_register_request(hostname)); 997 s.reset(); 998 stop_timer(); 999 } 1000 1001 void 1002 conf::isns_check(struct isns *isns) 1003 { 1004 int error; 1005 char hostname[256]; 1006 1007 if (conf_targets.empty() || conf_portal_groups.empty()) 1008 return; 1009 start_timer(conf_isns_timeout); 1010 freebsd::fd_up s = isns->connect(); 1011 if (!s) { 1012 stop_timer(); 1013 return; 1014 } 1015 error = gethostname(hostname, sizeof(hostname)); 1016 if (error != 0) 1017 log_err(1, "gethostname"); 1018 1019 if (!isns->send_request(s, isns_check_request(hostname))) { 1020 isns->send_request(s, isns_deregister_request(hostname)); 1021 isns->send_request(s, isns_register_request(hostname)); 1022 } 1023 s.reset(); 1024 stop_timer(); 1025 } 1026 1027 void 1028 conf::isns_deregister_targets(struct isns *isns) 1029 { 1030 int error; 1031 char hostname[256]; 1032 1033 if (conf_targets.empty() || conf_portal_groups.empty()) 1034 return; 1035 start_timer(conf_isns_timeout); 1036 freebsd::fd_up s = isns->connect(); 1037 if (!s) 1038 return; 1039 error = gethostname(hostname, sizeof(hostname)); 1040 if (error != 0) 1041 log_err(1, "gethostname"); 1042 1043 isns->send_request(s, isns_deregister_request(hostname)); 1044 s.reset(); 1045 stop_timer(); 1046 } 1047 1048 void 1049 conf::isns_schedule_update() 1050 { 1051 if (!conf_isns.empty()) 1052 start_timer((conf_isns_period + 2) / 3); 1053 } 1054 1055 void 1056 conf::isns_update() 1057 { 1058 stop_timer(); 1059 for (auto &kv : conf_isns) 1060 isns_check(&kv.second); 1061 1062 isns_schedule_update(); 1063 } 1064 1065 bool 1066 kports::add_port(std::string &name, uint32_t ctl_port) 1067 { 1068 const auto &pair = pports.try_emplace(name, name, ctl_port); 1069 if (!pair.second) { 1070 log_warnx("duplicate kernel port \"%s\" (%u)", name.c_str(), 1071 ctl_port); 1072 return (false); 1073 } 1074 1075 return (true); 1076 } 1077 1078 bool 1079 kports::has_port(std::string_view name) 1080 { 1081 return (pports.count(std::string(name)) > 0); 1082 } 1083 1084 struct pport * 1085 kports::find_port(std::string_view name) 1086 { 1087 auto it = pports.find(std::string(name)); 1088 if (it == pports.end()) 1089 return (nullptr); 1090 return (&it->second); 1091 } 1092 1093 port::port(struct target *target) : 1094 p_target(target) 1095 { 1096 target->add_port(this); 1097 } 1098 1099 void 1100 port::clear_references() 1101 { 1102 p_target->remove_port(this); 1103 } 1104 1105 portal_group_port::portal_group_port(struct target *target, 1106 struct portal_group *pg, auth_group_sp ag) : 1107 port(target), p_auth_group(ag), p_portal_group(pg) 1108 { 1109 p_portal_group->add_port(this); 1110 } 1111 1112 portal_group_port::portal_group_port(struct target *target, 1113 struct portal_group *pg, uint32_t ctl_port) : 1114 port(target), p_portal_group(pg) 1115 { 1116 p_ctl_port = ctl_port; 1117 p_portal_group->add_port(this); 1118 } 1119 1120 bool 1121 portal_group_port::is_dummy() const 1122 { 1123 return (p_portal_group->is_dummy()); 1124 } 1125 1126 void 1127 portal_group_port::clear_references() 1128 { 1129 p_portal_group->remove_port(this); 1130 port::clear_references(); 1131 } 1132 1133 bool 1134 conf::add_port(struct target *target, struct portal_group *pg, auth_group_sp ag) 1135 { 1136 std::string name = freebsd::stringf("%s-%s", pg->name(), 1137 target->name()); 1138 const auto &pair = conf_ports.try_emplace(name, pg->create_port(target, 1139 ag)); 1140 if (!pair.second) { 1141 log_warnx("duplicate port \"%s\"", name.c_str()); 1142 return (false); 1143 } 1144 1145 return (true); 1146 } 1147 1148 bool 1149 conf::add_port(struct target *target, struct portal_group *pg, 1150 uint32_t ctl_port) 1151 { 1152 std::string name = freebsd::stringf("%s-%s", pg->name(), 1153 target->name()); 1154 const auto &pair = conf_ports.try_emplace(name, pg->create_port(target, 1155 ctl_port)); 1156 if (!pair.second) { 1157 log_warnx("duplicate port \"%s\"", name.c_str()); 1158 return (false); 1159 } 1160 1161 return (true); 1162 } 1163 1164 bool 1165 conf::add_port(struct target *target, struct pport *pp) 1166 { 1167 std::string name = freebsd::stringf("%s-%s", pp->name(), 1168 target->name()); 1169 const auto &pair = conf_ports.try_emplace(name, 1170 std::make_unique<kernel_port>(target, pp)); 1171 if (!pair.second) { 1172 log_warnx("duplicate port \"%s\"", name.c_str()); 1173 return (false); 1174 } 1175 1176 pp->link(); 1177 return (true); 1178 } 1179 1180 bool 1181 conf::add_port(struct kports &kports, struct target *target, int pp, int vp) 1182 { 1183 struct pport *pport; 1184 1185 std::string pname = freebsd::stringf("ioctl/%d/%d", pp, vp); 1186 1187 pport = kports.find_port(pname); 1188 if (pport != NULL) 1189 return (add_port(target, pport)); 1190 1191 std::string name = pname + "-" + target->name(); 1192 const auto &pair = conf_ports.try_emplace(name, 1193 std::make_unique<ioctl_port>(target, pp, vp)); 1194 if (!pair.second) { 1195 log_warnx("duplicate port \"%s\"", name.c_str()); 1196 return (false); 1197 } 1198 1199 return (true); 1200 } 1201 1202 const struct port * 1203 portal_group::find_port(std::string_view target) const 1204 { 1205 auto it = pg_ports.find(std::string(target)); 1206 if (it == pg_ports.end()) 1207 return (nullptr); 1208 return (it->second); 1209 } 1210 1211 struct target * 1212 conf::add_controller(const char *name) 1213 { 1214 if (!nvmf_nqn_valid_strict(name)) { 1215 log_warnx("controller name \"%s\" is invalid for NVMe", name); 1216 return nullptr; 1217 } 1218 1219 /* 1220 * Normalize the name to lowercase to match iSCSI. 1221 */ 1222 std::string t_name(name); 1223 for (char &c : t_name) 1224 c = tolower(c); 1225 1226 auto const &pair = conf_controllers.try_emplace(t_name, 1227 nvmf_make_controller(this, t_name)); 1228 if (!pair.second) { 1229 log_warnx("duplicated controller \"%s\"", name); 1230 return nullptr; 1231 } 1232 1233 return pair.first->second.get(); 1234 } 1235 1236 struct target * 1237 conf::find_controller(std::string_view name) 1238 { 1239 auto it = conf_controllers.find(std::string(name)); 1240 if (it == conf_controllers.end()) 1241 return nullptr; 1242 return it->second.get(); 1243 } 1244 1245 target::target(struct conf *conf, const char *keyword, std::string_view name) : 1246 t_conf(conf), t_name(name) 1247 { 1248 t_label = freebsd::stringf("%s \"%s\"", keyword, t_name.c_str()); 1249 } 1250 1251 struct target * 1252 conf::add_target(const char *name) 1253 { 1254 if (!valid_iscsi_name(name, log_warnx)) 1255 return (nullptr); 1256 1257 /* 1258 * RFC 3722 requires us to normalize the name to lowercase. 1259 */ 1260 std::string t_name(name); 1261 for (char &c : t_name) 1262 c = tolower(c); 1263 1264 auto const &pair = conf_targets.try_emplace(t_name, 1265 iscsi_make_target(this, t_name)); 1266 if (!pair.second) { 1267 log_warnx("duplicated target \"%s\"", name); 1268 return (NULL); 1269 } 1270 1271 if (conf_first_target == nullptr) 1272 conf_first_target = pair.first->second.get(); 1273 return (pair.first->second.get()); 1274 } 1275 1276 struct target * 1277 conf::find_target(std::string_view name) 1278 { 1279 auto it = conf_targets.find(std::string(name)); 1280 if (it == conf_targets.end()) 1281 return (nullptr); 1282 return (it->second.get()); 1283 } 1284 1285 bool 1286 target::use_private_auth(const char *keyword) 1287 { 1288 if (t_private_auth) 1289 return (true); 1290 1291 if (t_auth_group != nullptr) { 1292 log_warnx("cannot use both auth-group and %s for %s", 1293 keyword, label()); 1294 return (false); 1295 } 1296 1297 t_auth_group = std::make_shared<struct auth_group>(t_label); 1298 t_private_auth = true; 1299 return (true); 1300 } 1301 1302 bool 1303 target::add_chap(const char *user, const char *secret) 1304 { 1305 if (!use_private_auth("chap")) 1306 return (false); 1307 return (t_auth_group->add_chap(user, secret)); 1308 } 1309 1310 bool 1311 target::add_chap_mutual(const char *user, const char *secret, 1312 const char *user2, const char *secret2) 1313 { 1314 if (!use_private_auth("chap-mutual")) 1315 return (false); 1316 return (t_auth_group->add_chap_mutual(user, secret, user2, secret2)); 1317 } 1318 1319 bool 1320 target::add_lun(u_int id, const char *lun_label, const char *lun_name) 1321 { 1322 struct lun *t_lun; 1323 1324 if (id >= MAX_LUNS) { 1325 log_warnx("%s too big for %s", lun_label, label()); 1326 return (false); 1327 } 1328 1329 if (t_luns[id] != NULL) { 1330 log_warnx("duplicate %s for %s", lun_label, label()); 1331 return (false); 1332 } 1333 1334 t_lun = t_conf->find_lun(lun_name); 1335 if (t_lun == NULL) { 1336 log_warnx("unknown LUN named %s used for %s", lun_name, 1337 label()); 1338 return (false); 1339 } 1340 1341 t_luns[id] = t_lun; 1342 return (true); 1343 } 1344 1345 bool 1346 target::set_alias(std::string_view alias) 1347 { 1348 if (has_alias()) { 1349 log_warnx("alias for %s specified more than once", label()); 1350 return (false); 1351 } 1352 t_alias = alias; 1353 return (true); 1354 } 1355 1356 bool 1357 target::set_auth_group(const char *ag_name) 1358 { 1359 if (t_auth_group != nullptr) { 1360 if (t_private_auth) 1361 log_warnx("cannot use both auth-group and explicit " 1362 "authorisations for %s", label()); 1363 else 1364 log_warnx("auth-group for %s " 1365 "specified more than once", label()); 1366 return (false); 1367 } 1368 t_auth_group = t_conf->find_auth_group(ag_name); 1369 if (t_auth_group == nullptr) { 1370 log_warnx("unknown auth-group \"%s\" for %s", 1371 ag_name, label()); 1372 return (false); 1373 } 1374 return (true); 1375 } 1376 1377 bool 1378 target::set_auth_type(const char *type) 1379 { 1380 if (!use_private_auth("auth-type")) 1381 return (false); 1382 return (t_auth_group->set_type(type)); 1383 } 1384 1385 bool 1386 target::set_physical_port(std::string_view pport) 1387 { 1388 if (!t_pport.empty()) { 1389 log_warnx("cannot set multiple physical ports for target " 1390 "\"%s\"", name()); 1391 return (false); 1392 } 1393 t_pport = pport; 1394 return (true); 1395 } 1396 1397 bool 1398 target::set_redirection(const char *addr) 1399 { 1400 if (!t_redirection.empty()) { 1401 log_warnx("cannot set redirection to \"%s\" for " 1402 "%s; already defined", 1403 addr, label()); 1404 return (false); 1405 } 1406 1407 t_redirection = addr; 1408 return (true); 1409 } 1410 1411 struct lun * 1412 target::start_lun(u_int id, const char *lun_label, const char *lun_name) 1413 { 1414 if (id >= MAX_LUNS) { 1415 log_warnx("%s too big for %s", lun_label, label()); 1416 return (nullptr); 1417 } 1418 1419 if (t_luns[id] != NULL) { 1420 log_warnx("duplicate %s for %s", lun_label, label()); 1421 return (nullptr); 1422 } 1423 1424 struct lun *new_lun = t_conf->add_lun(lun_name); 1425 if (new_lun == nullptr) 1426 return (nullptr); 1427 1428 new_lun->set_scsiname(lun_name); 1429 1430 t_luns[id] = new_lun; 1431 1432 return (new_lun); 1433 } 1434 1435 void 1436 target::add_port(struct port *port) 1437 { 1438 t_ports.push_back(port); 1439 } 1440 1441 void 1442 target::remove_port(struct port *port) 1443 { 1444 t_ports.remove(port); 1445 } 1446 1447 void 1448 target::remove_lun(struct lun *lun) 1449 { 1450 /* XXX: clang is not able to deduce the type without the cast. */ 1451 std::replace(t_luns.begin(), t_luns.end(), lun, 1452 static_cast<struct lun *>(nullptr)); 1453 } 1454 1455 void 1456 target::verify() 1457 { 1458 if (t_auth_group == nullptr) { 1459 t_auth_group = t_conf->find_auth_group("default"); 1460 assert(t_auth_group != nullptr); 1461 } 1462 if (t_ports.empty()) { 1463 struct portal_group *pg = default_portal_group(); 1464 assert(pg != NULL); 1465 t_conf->add_port(this, pg, nullptr); 1466 } 1467 1468 bool found = std::any_of(t_luns.begin(), t_luns.end(), 1469 [](struct lun *lun) { return (lun != nullptr); }); 1470 if (!found && t_redirection.empty()) 1471 log_warnx("no LUNs defined for %s", label()); 1472 if (found && !t_redirection.empty()) 1473 log_debugx("%s contains LUNs, but configured " 1474 "for redirection", label()); 1475 } 1476 1477 lun::lun(struct conf *conf, std::string_view name) 1478 : l_conf(conf), l_options(nvlist_create(0)), l_name(name) 1479 { 1480 } 1481 1482 struct lun * 1483 conf::add_lun(const char *name) 1484 { 1485 const auto &pair = conf_luns.try_emplace(name, 1486 std::make_unique<lun>(this, name)); 1487 if (!pair.second) { 1488 log_warnx("duplicated lun \"%s\"", name); 1489 return (NULL); 1490 } 1491 return (pair.first->second.get()); 1492 } 1493 1494 void 1495 conf::delete_target_luns(struct lun *lun) 1496 { 1497 for (const auto &kv : conf_targets) 1498 kv.second->remove_lun(lun); 1499 for (const auto &kv : conf_controllers) 1500 kv.second->remove_lun(lun); 1501 } 1502 1503 struct lun * 1504 conf::find_lun(std::string_view name) 1505 { 1506 auto it = conf_luns.find(std::string(name)); 1507 if (it == conf_luns.end()) 1508 return (nullptr); 1509 return (it->second.get()); 1510 } 1511 1512 static void 1513 nvlist_replace_string(nvlist_t *nvl, const char *name, const char *value) 1514 { 1515 if (nvlist_exists_string(nvl, name)) 1516 nvlist_free_string(nvl, name); 1517 nvlist_add_string(nvl, name, value); 1518 } 1519 1520 freebsd::nvlist_up 1521 lun::options() const 1522 { 1523 freebsd::nvlist_up nvl(nvlist_clone(l_options.get())); 1524 if (!l_path.empty()) 1525 nvlist_replace_string(nvl.get(), "file", l_path.c_str()); 1526 1527 nvlist_replace_string(nvl.get(), "ctld_name", l_name.c_str()); 1528 1529 if (!nvlist_exists_string(nvl.get(), "scsiname") && 1530 !l_scsiname.empty()) 1531 nvlist_add_string(nvl.get(), "scsiname", l_scsiname.c_str()); 1532 return (nvl); 1533 } 1534 1535 bool 1536 lun::add_option(const char *name, const char *value) 1537 { 1538 return (option_new(l_options.get(), name, value)); 1539 } 1540 1541 bool 1542 lun::set_backend(std::string_view value) 1543 { 1544 if (!l_backend.empty()) { 1545 log_warnx("backend for lun \"%s\" specified more than once", 1546 name()); 1547 return (false); 1548 } 1549 1550 l_backend = value; 1551 return (true); 1552 } 1553 1554 bool 1555 lun::set_blocksize(size_t value) 1556 { 1557 if (l_blocksize != 0) { 1558 log_warnx("blocksize for lun \"%s\" specified more than once", 1559 name()); 1560 return (false); 1561 } 1562 l_blocksize = value; 1563 return (true); 1564 } 1565 1566 bool 1567 lun::set_ctl_lun(uint32_t value) 1568 { 1569 if (l_ctl_lun >= 0) { 1570 log_warnx("ctl_lun for lun \"%s\" specified more than once", 1571 name()); 1572 return (false); 1573 } 1574 1575 l_ctl_lun = value; 1576 return (true); 1577 } 1578 1579 bool 1580 lun::set_device_type(uint8_t device_type) 1581 { 1582 if (device_type > 15) { 1583 log_warnx("invalid device-type \"%u\" for lun \"%s\"", 1584 device_type, name()); 1585 return (false); 1586 } 1587 1588 l_device_type = device_type; 1589 return (true); 1590 } 1591 1592 bool 1593 lun::set_device_type(const char *value) 1594 { 1595 const char *errstr; 1596 int device_type; 1597 1598 if (strcasecmp(value, "disk") == 0 || 1599 strcasecmp(value, "direct") == 0) 1600 device_type = T_DIRECT; 1601 else if (strcasecmp(value, "processor") == 0) 1602 device_type = T_PROCESSOR; 1603 else if (strcasecmp(value, "cd") == 0 || 1604 strcasecmp(value, "cdrom") == 0 || 1605 strcasecmp(value, "dvd") == 0 || 1606 strcasecmp(value, "dvdrom") == 0) 1607 device_type = T_CDROM; 1608 else { 1609 device_type = strtonum(value, 0, 15, &errstr); 1610 if (errstr != NULL) { 1611 log_warnx("invalid device-type \"%s\" for lun \"%s\"", 1612 value, name()); 1613 return (false); 1614 } 1615 } 1616 1617 l_device_type = device_type; 1618 return (true); 1619 } 1620 1621 bool 1622 lun::set_device_id(std::string_view value) 1623 { 1624 if (!l_device_id.empty()) { 1625 log_warnx("device_id for lun \"%s\" specified more than once", 1626 name()); 1627 return (false); 1628 } 1629 1630 l_device_id = value; 1631 return (true); 1632 } 1633 1634 bool 1635 lun::set_path(std::string_view value) 1636 { 1637 if (!l_path.empty()) { 1638 log_warnx("path for lun \"%s\" specified more than once", 1639 name()); 1640 return (false); 1641 } 1642 1643 l_path = value; 1644 return (true); 1645 } 1646 1647 void 1648 lun::set_scsiname(std::string_view value) 1649 { 1650 l_scsiname = value; 1651 } 1652 1653 bool 1654 lun::set_serial(std::string_view value) 1655 { 1656 if (!l_serial.empty()) { 1657 log_warnx("serial for lun \"%s\" specified more than once", 1658 name()); 1659 return (false); 1660 } 1661 1662 l_serial = value; 1663 return (true); 1664 } 1665 1666 bool 1667 lun::set_size(uint64_t value) 1668 { 1669 if (l_size != 0) { 1670 log_warnx("size for lun \"%s\" specified more than once", 1671 name()); 1672 return (false); 1673 } 1674 1675 l_size = value; 1676 return (true); 1677 } 1678 1679 1680 bool 1681 lun::changed(const struct lun &newlun) const 1682 { 1683 if (l_backend != newlun.l_backend) { 1684 log_debugx("backend for lun \"%s\", CTL lun %d changed; " 1685 "removing", name(), l_ctl_lun); 1686 return (true); 1687 } 1688 if (l_blocksize != newlun.l_blocksize) { 1689 log_debugx("blocksize for lun \"%s\", CTL lun %d changed; " 1690 "removing", name(), l_ctl_lun); 1691 return (true); 1692 } 1693 if (l_device_id != newlun.l_device_id) { 1694 log_debugx("device-id for lun \"%s\", CTL lun %d changed; " 1695 "removing", name(), l_ctl_lun); 1696 return (true); 1697 } 1698 if (l_path != newlun.l_path) { 1699 log_debugx("path for lun \"%s\", CTL lun %d, changed; " 1700 "removing", name(), l_ctl_lun); 1701 return (true); 1702 } 1703 if (l_serial != newlun.l_serial) { 1704 log_debugx("serial for lun \"%s\", CTL lun %d changed; " 1705 "removing", name(), l_ctl_lun); 1706 return (true); 1707 } 1708 return (false); 1709 } 1710 1711 bool 1712 option_new(nvlist_t *nvl, const char *name, const char *value) 1713 { 1714 int error; 1715 1716 if (nvlist_exists_string(nvl, name)) { 1717 log_warnx("duplicated option \"%s\"", name); 1718 return (false); 1719 } 1720 1721 nvlist_add_string(nvl, name, value); 1722 error = nvlist_error(nvl); 1723 if (error != 0) { 1724 log_warnc(error, "failed to add option \"%s\"", name); 1725 return (false); 1726 } 1727 return (true); 1728 } 1729 1730 bool 1731 lun::verify() 1732 { 1733 if (l_backend.empty()) 1734 l_backend = "block"; 1735 if (l_backend == "block") { 1736 if (l_path.empty()) { 1737 log_warnx("missing path for lun \"%s\"", 1738 name()); 1739 return (false); 1740 } 1741 } else if (l_backend == "ramdisk") { 1742 if (l_size == 0) { 1743 log_warnx("missing size for ramdisk-backed lun \"%s\"", 1744 name()); 1745 return (false); 1746 } 1747 if (!l_path.empty()) { 1748 log_warnx("path must not be specified " 1749 "for ramdisk-backed lun \"%s\"", 1750 name()); 1751 return (false); 1752 } 1753 } 1754 if (l_blocksize == 0) { 1755 if (l_device_type == T_CDROM) 1756 l_blocksize = DEFAULT_CD_BLOCKSIZE; 1757 else 1758 l_blocksize = DEFAULT_BLOCKSIZE; 1759 } else if (l_blocksize < 0) { 1760 log_warnx("invalid blocksize %d for lun \"%s\"; " 1761 "must be larger than 0", l_blocksize, name()); 1762 return (false); 1763 } 1764 if (l_size != 0 && (l_size % l_blocksize) != 0) { 1765 log_warnx("invalid size for lun \"%s\"; " 1766 "must be multiple of blocksize", name()); 1767 return (false); 1768 } 1769 return (true); 1770 } 1771 1772 bool 1773 conf::verify() 1774 { 1775 if (conf_pidfile_path.empty()) 1776 conf_pidfile_path = DEFAULT_PIDFILE; 1777 1778 std::unordered_map<std::string, struct lun *> path_map; 1779 for (const auto &kv : conf_luns) { 1780 struct lun *lun = kv.second.get(); 1781 if (!lun->verify()) 1782 return (false); 1783 1784 const std::string &path = lun->path(); 1785 if (path.empty()) 1786 continue; 1787 1788 const auto &pair = path_map.try_emplace(path, lun); 1789 if (!pair.second) { 1790 struct lun *lun2 = pair.first->second; 1791 log_debugx("WARNING: path \"%s\" duplicated " 1792 "between lun \"%s\", and " 1793 "lun \"%s\"", path.c_str(), 1794 lun->name(), lun2->name()); 1795 } 1796 } 1797 1798 for (auto &kv : conf_targets) { 1799 kv.second->verify(); 1800 } 1801 for (auto &kv : conf_controllers) { 1802 kv.second->verify(); 1803 } 1804 for (auto &kv : conf_portal_groups) { 1805 kv.second->verify(this); 1806 } 1807 for (auto &kv : conf_transport_groups) { 1808 kv.second->verify(this); 1809 } 1810 for (const auto &kv : conf_auth_groups) { 1811 const std::string &ag_name = kv.first; 1812 if (ag_name == "default" || 1813 ag_name == "no-authentication" || 1814 ag_name == "no-access") 1815 continue; 1816 1817 if (kv.second.use_count() == 1) { 1818 log_warnx("auth-group \"%s\" not assigned " 1819 "to any target", ag_name.c_str()); 1820 } 1821 } 1822 1823 return (true); 1824 } 1825 1826 bool 1827 portal::reuse_socket(struct portal &oldp) 1828 { 1829 struct kevent kev; 1830 1831 if (p_listen != oldp.p_listen) 1832 return (false); 1833 1834 if (!oldp.p_socket) 1835 return (false); 1836 1837 EV_SET(&kev, oldp.p_socket, EVFILT_READ, EV_ADD, 0, 0, this); 1838 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == -1) 1839 return (false); 1840 1841 p_socket = std::move(oldp.p_socket); 1842 return (true); 1843 } 1844 1845 bool 1846 portal::init_socket() 1847 { 1848 struct portal_group *pg = portal_group(); 1849 struct kevent kev; 1850 freebsd::fd_up s; 1851 int error; 1852 int one = 1; 1853 1854 #ifdef ICL_KERNEL_PROXY 1855 if (proxy_mode) { 1856 int id = pg->conf()->add_proxy_portal(this); 1857 log_debugx("listening on %s, %s \"%s\", " 1858 "portal id %d, using ICL proxy", listen(), pg->keyword(), 1859 pg->name(), id); 1860 kernel_listen(ai(), protocol() == ISER, id); 1861 return (true); 1862 } 1863 #endif 1864 assert(proxy_mode == false); 1865 assert(protocol() != portal_protocol::ISER); 1866 1867 log_debugx("listening on %s, %s \"%s\"", listen(), pg->keyword(), 1868 pg->name()); 1869 s = ::socket(p_ai->ai_family, p_ai->ai_socktype, p_ai->ai_protocol); 1870 if (!s) { 1871 log_warn("socket(2) failed for %s", listen()); 1872 return (false); 1873 } 1874 1875 if (setsockopt(s, SOL_SOCKET, SO_NO_DDP, &one, 1876 sizeof(one)) == -1) 1877 log_warn("setsockopt(SO_NO_DDP) failed for %s", listen()); 1878 error = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, 1879 sizeof(one)); 1880 if (error != 0) { 1881 log_warn("setsockopt(SO_REUSEADDR) failed for %s", listen()); 1882 return (false); 1883 } 1884 1885 if (pg->dscp() != -1) { 1886 /* Only allow the 6-bit DSCP field to be modified */ 1887 int tos = pg->dscp() << 2; 1888 switch (p_ai->ai_family) { 1889 case AF_INET: 1890 if (setsockopt(s, IPPROTO_IP, IP_TOS, 1891 &tos, sizeof(tos)) == -1) 1892 log_warn("setsockopt(IP_TOS) failed for %s", 1893 listen()); 1894 break; 1895 case AF_INET6: 1896 if (setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, 1897 &tos, sizeof(tos)) == -1) 1898 log_warn("setsockopt(IPV6_TCLASS) failed for %s", 1899 listen()); 1900 break; 1901 } 1902 } 1903 if (pg->pcp() != -1) { 1904 int pcp = pg->pcp(); 1905 switch (p_ai->ai_family) { 1906 case AF_INET: 1907 if (setsockopt(s, IPPROTO_IP, IP_VLAN_PCP, 1908 &pcp, sizeof(pcp)) == -1) 1909 log_warn("setsockopt(IP_VLAN_PCP) failed for %s", 1910 listen()); 1911 break; 1912 case AF_INET6: 1913 if (setsockopt(s, IPPROTO_IPV6, IPV6_VLAN_PCP, 1914 &pcp, sizeof(pcp)) == -1) 1915 log_warn("setsockopt(IPV6_VLAN_PCP) failed for %s", 1916 listen()); 1917 break; 1918 } 1919 } 1920 1921 if (!init_socket_options(s)) 1922 return (false); 1923 1924 error = bind(s, p_ai->ai_addr, p_ai->ai_addrlen); 1925 if (error != 0) { 1926 log_warn("bind(2) failed for %s", listen()); 1927 return (false); 1928 } 1929 error = ::listen(s, -1); 1930 if (error != 0) { 1931 log_warn("listen(2) failed for %s", listen()); 1932 return (false); 1933 } 1934 EV_SET(&kev, s, EVFILT_READ, EV_ADD, 0, 0, this); 1935 error = kevent(kqfd, &kev, 1, NULL, 0, NULL); 1936 if (error == -1) { 1937 log_warn("kevent(2) failed to register for %s", listen()); 1938 return (false); 1939 } 1940 p_socket = std::move(s); 1941 return (true); 1942 } 1943 1944 bool 1945 conf::reuse_portal_group_socket(struct portal &newp) 1946 { 1947 for (auto &kv : conf_portal_groups) { 1948 struct portal_group &pg = *kv.second; 1949 1950 if (pg.reuse_socket(newp)) 1951 return (true); 1952 } 1953 for (auto &kv : conf_transport_groups) { 1954 struct portal_group &pg = *kv.second; 1955 1956 if (pg.reuse_socket(newp)) 1957 return (true); 1958 } 1959 return (false); 1960 } 1961 1962 int 1963 conf::apply(struct conf *oldconf) 1964 { 1965 int cumulated_error = 0; 1966 1967 if (oldconf->conf_debug != conf_debug) { 1968 log_debugx("changing debug level to %d", conf_debug); 1969 log_init(conf_debug); 1970 } 1971 1972 /* 1973 * On startup, oldconf created via conf_new_from_kernel will 1974 * not contain a valid pidfile_path, and the current 1975 * conf_pidfile will already own the pidfile. On shutdown, 1976 * the temporary newconf will not contain a valid 1977 * pidfile_path, and the pidfile will be cleaned up when the 1978 * oldconf is deleted. 1979 */ 1980 if (!oldconf->conf_pidfile_path.empty() && 1981 !conf_pidfile_path.empty()) { 1982 if (oldconf->conf_pidfile_path != conf_pidfile_path) { 1983 /* pidfile has changed. rename it */ 1984 log_debugx("moving pidfile to %s", 1985 conf_pidfile_path.c_str()); 1986 if (rename(oldconf->conf_pidfile_path.c_str(), 1987 conf_pidfile_path.c_str()) != 0) { 1988 log_err(1, "renaming pidfile %s -> %s", 1989 oldconf->conf_pidfile_path.c_str(), 1990 conf_pidfile_path.c_str()); 1991 } 1992 } 1993 conf_pidfile = std::move(oldconf->conf_pidfile); 1994 } 1995 1996 /* 1997 * Go through the new portal groups, assigning tags or preserving old. 1998 */ 1999 for (auto &kv : conf_portal_groups) { 2000 struct portal_group &newpg = *kv.second; 2001 2002 if (newpg.tag() != 0) 2003 continue; 2004 auto it = oldconf->conf_portal_groups.find(kv.first); 2005 if (it != oldconf->conf_portal_groups.end()) 2006 newpg.set_tag(it->second->tag()); 2007 else 2008 newpg.allocate_tag(); 2009 } 2010 for (auto &kv : conf_transport_groups) { 2011 struct portal_group &newpg = *kv.second; 2012 2013 if (newpg.tag() != 0) 2014 continue; 2015 auto it = oldconf->conf_transport_groups.find(kv.first); 2016 if (it != oldconf->conf_transport_groups.end()) 2017 newpg.set_tag(it->second->tag()); 2018 else 2019 newpg.allocate_tag(); 2020 } 2021 2022 /* Deregister on removed iSNS servers. */ 2023 for (auto &kv : oldconf->conf_isns) { 2024 if (conf_isns.count(kv.first) == 0) 2025 oldconf->isns_deregister_targets(&kv.second); 2026 } 2027 2028 /* 2029 * XXX: If target or lun removal fails, we should somehow "move" 2030 * the old lun or target into this, so that subsequent 2031 * conf::apply() would try to remove them again. That would 2032 * be somewhat hairy, though, and lun deletion failures don't 2033 * really happen, so leave it as it is for now. 2034 */ 2035 /* 2036 * First, remove any ports present in the old configuration 2037 * and missing in the new one. 2038 */ 2039 for (const auto &kv : oldconf->conf_ports) { 2040 const std::string &name = kv.first; 2041 port *oldport = kv.second.get(); 2042 2043 if (oldport->is_dummy()) 2044 continue; 2045 const auto it = conf_ports.find(name); 2046 if (it != conf_ports.end() && !it->second->is_dummy()) 2047 continue; 2048 log_debugx("removing port \"%s\"", name.c_str()); 2049 if (!oldport->kernel_remove()) { 2050 log_warnx("failed to remove port %s", name.c_str()); 2051 /* 2052 * XXX: Uncomment after fixing the root cause. 2053 * 2054 * cumulated_error++; 2055 */ 2056 } 2057 } 2058 2059 /* 2060 * Second, remove any LUNs present in the old configuration 2061 * and missing in the new one. 2062 */ 2063 for (auto it = oldconf->conf_luns.begin(); 2064 it != oldconf->conf_luns.end(); ) { 2065 struct lun *oldlun = it->second.get(); 2066 2067 auto newit = conf_luns.find(it->first); 2068 if (newit == conf_luns.end()) { 2069 log_debugx("lun \"%s\", CTL lun %d " 2070 "not found in new configuration; " 2071 "removing", oldlun->name(), oldlun->ctl_lun()); 2072 if (!oldlun->kernel_remove()) { 2073 log_warnx("failed to remove lun \"%s\", " 2074 "CTL lun %d", 2075 oldlun->name(), oldlun->ctl_lun()); 2076 cumulated_error++; 2077 } 2078 it++; 2079 continue; 2080 } 2081 2082 /* 2083 * Also remove the LUNs changed by more than size. 2084 */ 2085 struct lun *newlun = newit->second.get(); 2086 if (oldlun->changed(*newlun)) { 2087 if (!oldlun->kernel_remove()) { 2088 log_warnx("failed to remove lun \"%s\", " 2089 "CTL lun %d", 2090 oldlun->name(), oldlun->ctl_lun()); 2091 cumulated_error++; 2092 } 2093 2094 /* 2095 * Delete the lun from the old configuration 2096 * so it is added as a new LUN below. 2097 */ 2098 it = oldconf->conf_luns.erase(it); 2099 continue; 2100 } 2101 2102 newlun->set_ctl_lun(oldlun->ctl_lun()); 2103 it++; 2104 } 2105 2106 for (auto it = conf_luns.begin(); it != conf_luns.end(); ) { 2107 struct lun *newlun = it->second.get(); 2108 2109 auto oldit = oldconf->conf_luns.find(it->first); 2110 if (oldit != oldconf->conf_luns.end()) { 2111 log_debugx("modifying lun \"%s\", CTL lun %d", 2112 newlun->name(), newlun->ctl_lun()); 2113 if (!newlun->kernel_modify()) { 2114 log_warnx("failed to " 2115 "modify lun \"%s\", CTL lun %d", 2116 newlun->name(), newlun->ctl_lun()); 2117 cumulated_error++; 2118 } 2119 it++; 2120 continue; 2121 } 2122 2123 log_debugx("adding lun \"%s\"", newlun->name()); 2124 if (!newlun->kernel_add()) { 2125 log_warnx("failed to add lun \"%s\"", newlun->name()); 2126 delete_target_luns(newlun); 2127 it = conf_luns.erase(it); 2128 cumulated_error++; 2129 } else 2130 it++; 2131 } 2132 2133 /* 2134 * Now add new ports or modify existing ones. 2135 */ 2136 for (auto it = conf_ports.begin(); it != conf_ports.end(); ) { 2137 const std::string &name = it->first; 2138 port *newport = it->second.get(); 2139 2140 if (newport->is_dummy()) { 2141 it++; 2142 continue; 2143 } 2144 const auto oldit = oldconf->conf_ports.find(name); 2145 if (oldit == oldconf->conf_ports.end() || 2146 oldit->second->is_dummy()) { 2147 log_debugx("adding port \"%s\"", name.c_str()); 2148 if (!newport->kernel_add()) { 2149 log_warnx("failed to add port %s", 2150 name.c_str()); 2151 2152 /* 2153 * XXX: Uncomment after fixing the 2154 * root cause. 2155 * 2156 * cumulated_error++; 2157 */ 2158 2159 /* 2160 * conf "owns" the port, but other 2161 * objects contain pointers to this 2162 * port that must be removed before 2163 * deleting the port. 2164 */ 2165 newport->clear_references(); 2166 it = conf_ports.erase(it); 2167 } else 2168 it++; 2169 } else { 2170 log_debugx("updating port \"%s\"", name.c_str()); 2171 if (!newport->kernel_update(oldit->second.get())) 2172 log_warnx("failed to update port %s", 2173 name.c_str()); 2174 it++; 2175 } 2176 } 2177 2178 /* 2179 * Go through the new portals, opening the sockets as necessary. 2180 */ 2181 for (auto &kv : conf_portal_groups) { 2182 cumulated_error += kv.second->open_sockets(*oldconf); 2183 } 2184 for (auto &kv : conf_transport_groups) { 2185 cumulated_error += kv.second->open_sockets(*oldconf); 2186 } 2187 2188 /* 2189 * Go through the no longer used sockets, closing them. 2190 */ 2191 for (auto &kv : oldconf->conf_portal_groups) { 2192 kv.second->close_sockets(); 2193 } 2194 for (auto &kv : oldconf->conf_transport_groups) { 2195 kv.second->close_sockets(); 2196 } 2197 2198 /* (Re-)Register on remaining/new iSNS servers. */ 2199 for (auto &kv : conf_isns) { 2200 auto it = oldconf->conf_isns.find(kv.first); 2201 if (it == oldconf->conf_isns.end()) 2202 isns_register_targets(&kv.second, nullptr); 2203 else 2204 isns_register_targets(&kv.second, oldconf); 2205 } 2206 2207 isns_schedule_update(); 2208 2209 return (cumulated_error); 2210 } 2211 2212 bool 2213 timed_out(void) 2214 { 2215 2216 return (sigalrm_received); 2217 } 2218 2219 static void 2220 sigalrm_handler_fatal(int dummy __unused) 2221 { 2222 /* 2223 * It would be easiest to just log an error and exit. We can't 2224 * do this, though, because log_errx() is not signal safe, since 2225 * it calls syslog(3). Instead, set a flag checked by pdu_send() 2226 * and pdu_receive(), to call log_errx() there. Should they fail 2227 * to notice, we'll exit here one second later. 2228 */ 2229 if (sigalrm_received) { 2230 /* 2231 * Oh well. Just give up and quit. 2232 */ 2233 _exit(2); 2234 } 2235 2236 sigalrm_received = true; 2237 } 2238 2239 static void 2240 sigalrm_handler(int dummy __unused) 2241 { 2242 2243 sigalrm_received = true; 2244 } 2245 2246 void 2247 stop_timer() 2248 { 2249 struct itimerval itv; 2250 int error; 2251 2252 log_debugx("session timeout disabled"); 2253 bzero(&itv, sizeof(itv)); 2254 error = setitimer(ITIMER_REAL, &itv, NULL); 2255 if (error != 0) 2256 log_err(1, "setitimer"); 2257 sigalrm_received = false; 2258 } 2259 2260 void 2261 start_timer(int timeout, bool fatal) 2262 { 2263 struct sigaction sa; 2264 struct itimerval itv; 2265 int error; 2266 2267 if (timeout <= 0) { 2268 stop_timer(); 2269 return; 2270 } 2271 2272 sigalrm_received = false; 2273 bzero(&sa, sizeof(sa)); 2274 if (fatal) 2275 sa.sa_handler = sigalrm_handler_fatal; 2276 else 2277 sa.sa_handler = sigalrm_handler; 2278 sigfillset(&sa.sa_mask); 2279 error = sigaction(SIGALRM, &sa, NULL); 2280 if (error != 0) 2281 log_err(1, "sigaction"); 2282 2283 /* 2284 * First SIGALRM will arive after timeout seconds. 2285 * If we do nothing, another one will arrive a second later. 2286 */ 2287 log_debugx("setting session timeout to %d seconds", timeout); 2288 bzero(&itv, sizeof(itv)); 2289 itv.it_interval.tv_sec = 1; 2290 itv.it_value.tv_sec = timeout; 2291 error = setitimer(ITIMER_REAL, &itv, NULL); 2292 if (error != 0) 2293 log_err(1, "setitimer"); 2294 } 2295 2296 static int 2297 wait_for_children(bool block) 2298 { 2299 pid_t pid; 2300 int status; 2301 int num = 0; 2302 2303 for (;;) { 2304 /* 2305 * If "block" is true, wait for at least one process. 2306 */ 2307 if (block && num == 0) 2308 pid = wait4(-1, &status, 0, NULL); 2309 else 2310 pid = wait4(-1, &status, WNOHANG, NULL); 2311 if (pid <= 0) 2312 break; 2313 if (WIFSIGNALED(status)) { 2314 log_warnx("child process %d terminated with signal %d", 2315 pid, WTERMSIG(status)); 2316 } else if (WEXITSTATUS(status) != 0) { 2317 log_warnx("child process %d terminated with exit status %d", 2318 pid, WEXITSTATUS(status)); 2319 } else { 2320 log_debugx("child process %d terminated gracefully", pid); 2321 } 2322 num++; 2323 } 2324 2325 return (num); 2326 } 2327 2328 static void 2329 handle_connection(struct portal *portal, freebsd::fd_up fd, 2330 const struct sockaddr *client_sa, bool dont_fork) 2331 { 2332 struct portal_group *pg; 2333 int error; 2334 pid_t pid; 2335 char host[NI_MAXHOST + 1]; 2336 struct conf *conf; 2337 2338 pg = portal->portal_group(); 2339 conf = pg->conf(); 2340 2341 if (dont_fork) { 2342 log_debugx("incoming connection; not forking due to -d flag"); 2343 } else { 2344 nchildren -= wait_for_children(false); 2345 assert(nchildren >= 0); 2346 2347 while (conf->maxproc() > 0 && nchildren >= conf->maxproc()) { 2348 log_debugx("maxproc limit of %d child processes hit; " 2349 "waiting for child process to exit", 2350 conf->maxproc()); 2351 nchildren -= wait_for_children(true); 2352 assert(nchildren >= 0); 2353 } 2354 log_debugx("incoming connection; forking child process #%d", 2355 nchildren); 2356 nchildren++; 2357 pid = fork(); 2358 if (pid < 0) 2359 log_err(1, "fork"); 2360 if (pid > 0) 2361 return; 2362 conf->close_pidfile(); 2363 } 2364 2365 error = getnameinfo(client_sa, client_sa->sa_len, 2366 host, sizeof(host), NULL, 0, NI_NUMERICHOST); 2367 if (error != 0) 2368 log_errx(1, "getnameinfo: %s", gai_strerror(error)); 2369 2370 log_debugx("accepted connection from %s; portal group \"%s\"", 2371 host, pg->name()); 2372 log_set_peer_addr(host); 2373 setproctitle("%s", host); 2374 2375 portal->handle_connection(std::move(fd), host, client_sa); 2376 log_debugx("nothing more to do; exiting"); 2377 exit(0); 2378 } 2379 2380 static void 2381 main_loop(bool dont_fork) 2382 { 2383 struct kevent kev; 2384 struct portal *portal; 2385 struct sockaddr_storage client_sa; 2386 socklen_t client_salen; 2387 #ifdef ICL_KERNEL_PROXY 2388 int connection_id; 2389 int portal_id; 2390 #endif 2391 int error, client_fd; 2392 2393 for (;;) { 2394 if (sighup_received || sigterm_received || timed_out()) 2395 return; 2396 2397 #ifdef ICL_KERNEL_PROXY 2398 if (proxy_mode) { 2399 client_salen = sizeof(client_sa); 2400 kernel_accept(&connection_id, &portal_id, 2401 (struct sockaddr *)&client_sa, &client_salen); 2402 assert(client_salen >= client_sa.ss_len); 2403 2404 log_debugx("incoming connection, id %d, portal id %d", 2405 connection_id, portal_id); 2406 portal = conf->proxy_portal(portal_id); 2407 if (portal == nullptr) 2408 log_errx(1, 2409 "kernel returned invalid portal_id %d", 2410 portal_id); 2411 2412 handle_connection(portal, connection_id, 2413 (struct sockaddr *)&client_sa, dont_fork); 2414 } else { 2415 #endif 2416 assert(proxy_mode == false); 2417 2418 error = kevent(kqfd, NULL, 0, &kev, 1, NULL); 2419 if (error == -1) { 2420 if (errno == EINTR) 2421 continue; 2422 log_err(1, "kevent"); 2423 } 2424 2425 switch (kev.filter) { 2426 case EVFILT_READ: 2427 portal = reinterpret_cast<struct portal *>(kev.udata); 2428 assert(portal->socket() == (int)kev.ident); 2429 2430 client_salen = sizeof(client_sa); 2431 client_fd = accept(portal->socket(), 2432 (struct sockaddr *)&client_sa, 2433 &client_salen); 2434 if (client_fd < 0) { 2435 if (errno == ECONNABORTED) 2436 continue; 2437 log_err(1, "accept"); 2438 } 2439 assert(client_salen >= client_sa.ss_len); 2440 2441 handle_connection(portal, client_fd, 2442 (struct sockaddr *)&client_sa, dont_fork); 2443 break; 2444 default: 2445 __assert_unreachable(); 2446 } 2447 #ifdef ICL_KERNEL_PROXY 2448 } 2449 #endif 2450 } 2451 } 2452 2453 static void 2454 sighup_handler(int dummy __unused) 2455 { 2456 2457 sighup_received = true; 2458 } 2459 2460 static void 2461 sigterm_handler(int dummy __unused) 2462 { 2463 2464 sigterm_received = true; 2465 } 2466 2467 static void 2468 sigchld_handler(int dummy __unused) 2469 { 2470 2471 /* 2472 * The only purpose of this handler is to make SIGCHLD 2473 * interrupt the ISCSIDWAIT ioctl(2), so we can call 2474 * wait_for_children(). 2475 */ 2476 } 2477 2478 static void 2479 register_signals(void) 2480 { 2481 struct sigaction sa; 2482 int error; 2483 2484 bzero(&sa, sizeof(sa)); 2485 sa.sa_handler = sighup_handler; 2486 sigfillset(&sa.sa_mask); 2487 error = sigaction(SIGHUP, &sa, NULL); 2488 if (error != 0) 2489 log_err(1, "sigaction"); 2490 2491 sa.sa_handler = sigterm_handler; 2492 error = sigaction(SIGTERM, &sa, NULL); 2493 if (error != 0) 2494 log_err(1, "sigaction"); 2495 2496 sa.sa_handler = sigterm_handler; 2497 error = sigaction(SIGINT, &sa, NULL); 2498 if (error != 0) 2499 log_err(1, "sigaction"); 2500 2501 sa.sa_handler = sigchld_handler; 2502 error = sigaction(SIGCHLD, &sa, NULL); 2503 if (error != 0) 2504 log_err(1, "sigaction"); 2505 } 2506 2507 static void 2508 check_perms(const char *path) 2509 { 2510 struct stat sb; 2511 int error; 2512 2513 error = stat(path, &sb); 2514 if (error != 0) { 2515 log_warn("stat"); 2516 return; 2517 } 2518 if (sb.st_mode & S_IWOTH) { 2519 log_warnx("%s is world-writable", path); 2520 } else if (sb.st_mode & S_IROTH) { 2521 log_warnx("%s is world-readable", path); 2522 } else if (sb.st_mode & S_IXOTH) { 2523 /* 2524 * Ok, this one doesn't matter, but still do it, 2525 * just for consistency. 2526 */ 2527 log_warnx("%s is world-executable", path); 2528 } 2529 2530 /* 2531 * XXX: Should we also check for owner != 0? 2532 */ 2533 } 2534 2535 static conf_up 2536 conf_new_from_file(const char *path, bool ucl) 2537 { 2538 struct auth_group *ag; 2539 struct portal_group *pg; 2540 bool valid; 2541 2542 log_debugx("obtaining configuration from %s", path); 2543 2544 conf_up conf = std::make_unique<struct conf>(); 2545 2546 ag = conf->add_auth_group("default"); 2547 assert(ag != NULL); 2548 2549 ag = conf->add_auth_group("no-authentication"); 2550 assert(ag != NULL); 2551 ag->set_type(auth_type::NO_AUTHENTICATION); 2552 2553 ag = conf->add_auth_group("no-access"); 2554 assert(ag != NULL); 2555 ag->set_type(auth_type::DENY); 2556 2557 pg = conf->add_portal_group("default"); 2558 assert(pg != NULL); 2559 2560 pg = conf->add_transport_group("default"); 2561 assert(pg != NULL); 2562 2563 conf_start(conf.get()); 2564 if (ucl) 2565 valid = uclparse_conf(path); 2566 else 2567 valid = parse_conf(path); 2568 conf_finish(); 2569 2570 if (!valid) { 2571 conf.reset(); 2572 return {}; 2573 } 2574 2575 check_perms(path); 2576 2577 if (!conf->default_auth_group_defined()) { 2578 log_debugx("auth-group \"default\" not defined; " 2579 "going with defaults"); 2580 ag = conf->find_auth_group("default").get(); 2581 assert(ag != NULL); 2582 ag->set_type(auth_type::DENY); 2583 } 2584 2585 if (!conf->default_portal_group_defined()) { 2586 log_debugx("portal-group \"default\" not defined; " 2587 "going with defaults"); 2588 pg = conf->find_portal_group("default"); 2589 assert(pg != NULL); 2590 pg->add_default_portals(); 2591 } 2592 2593 if (!conf->default_portal_group_defined()) { 2594 log_debugx("transport-group \"default\" not defined; " 2595 "going with defaults"); 2596 pg = conf->find_transport_group("default"); 2597 assert(pg != NULL); 2598 pg->add_default_portals(); 2599 } 2600 2601 if (!conf->verify()) { 2602 conf.reset(); 2603 return {}; 2604 } 2605 2606 return (conf); 2607 } 2608 2609 /* 2610 * If the config file specifies physical ports for any target, associate them 2611 * with the config file. If necessary, create them. 2612 */ 2613 bool 2614 conf::add_pports(struct kports &kports) 2615 { 2616 struct pport *pp; 2617 int ret, i_pp, i_vp; 2618 2619 for (auto &kv : conf_targets) { 2620 struct target *targ = kv.second.get(); 2621 2622 if (!targ->has_pport()) 2623 continue; 2624 2625 ret = sscanf(targ->pport(), "ioctl/%d/%d", &i_pp, &i_vp); 2626 if (ret > 0) { 2627 if (!add_port(kports, targ, i_pp, i_vp)) { 2628 log_warnx("can't create new ioctl port " 2629 "for %s", targ->label()); 2630 return (false); 2631 } 2632 2633 continue; 2634 } 2635 2636 pp = kports.find_port(targ->pport()); 2637 if (pp == NULL) { 2638 log_warnx("unknown port \"%s\" for %s", 2639 targ->pport(), targ->label()); 2640 return (false); 2641 } 2642 if (pp->linked()) { 2643 log_warnx("can't link port \"%s\" to %s, " 2644 "port already linked to some target", 2645 targ->pport(), targ->label()); 2646 return (false); 2647 } 2648 if (!add_port(targ, pp)) { 2649 log_warnx("can't link port \"%s\" to %s", 2650 targ->pport(), targ->label()); 2651 return (false); 2652 } 2653 } 2654 return (true); 2655 } 2656 2657 int 2658 main(int argc, char **argv) 2659 { 2660 struct kports kports; 2661 const char *config_path = DEFAULT_CONFIG_PATH; 2662 int debug = 0, ch, error; 2663 bool daemonize = true; 2664 bool test_config = false; 2665 bool use_ucl = false; 2666 2667 while ((ch = getopt(argc, argv, "dtuf:R")) != -1) { 2668 switch (ch) { 2669 case 'd': 2670 daemonize = false; 2671 debug++; 2672 break; 2673 case 't': 2674 test_config = true; 2675 break; 2676 case 'u': 2677 use_ucl = true; 2678 break; 2679 case 'f': 2680 config_path = optarg; 2681 break; 2682 case 'R': 2683 #ifndef ICL_KERNEL_PROXY 2684 log_errx(1, "ctld(8) compiled without ICL_KERNEL_PROXY " 2685 "does not support iSER protocol"); 2686 #endif 2687 proxy_mode = true; 2688 break; 2689 case '?': 2690 default: 2691 usage(); 2692 } 2693 } 2694 argc -= optind; 2695 if (argc != 0) 2696 usage(); 2697 2698 log_init(debug); 2699 kernel_init(); 2700 2701 conf_up newconf = conf_new_from_file(config_path, use_ucl); 2702 2703 if (newconf == NULL) 2704 log_errx(1, "configuration error; exiting"); 2705 2706 if (test_config) 2707 return (0); 2708 2709 newconf->open_pidfile(); 2710 2711 register_signals(); 2712 2713 conf_up oldconf = conf_new_from_kernel(kports); 2714 2715 if (debug > 0) { 2716 oldconf->set_debug(debug); 2717 newconf->set_debug(debug); 2718 } 2719 2720 if (!newconf->add_pports(kports)) 2721 log_errx(1, "Error associating physical ports; exiting"); 2722 2723 if (daemonize) { 2724 log_debugx("daemonizing"); 2725 if (daemon(0, 0) == -1) { 2726 log_warn("cannot daemonize"); 2727 return (1); 2728 } 2729 } 2730 2731 kqfd = kqueue(); 2732 if (kqfd == -1) { 2733 log_warn("Cannot create kqueue"); 2734 return (1); 2735 } 2736 2737 error = newconf->apply(oldconf.get()); 2738 if (error != 0) 2739 log_errx(1, "failed to apply configuration; exiting"); 2740 2741 oldconf.reset(); 2742 2743 newconf->write_pidfile(); 2744 2745 newconf->isns_schedule_update(); 2746 2747 for (;;) { 2748 main_loop(!daemonize); 2749 if (sighup_received) { 2750 sighup_received = false; 2751 log_debugx("received SIGHUP, reloading configuration"); 2752 conf_up tmpconf = conf_new_from_file(config_path, 2753 use_ucl); 2754 2755 if (tmpconf == NULL) { 2756 log_warnx("configuration error, " 2757 "continuing with old configuration"); 2758 } else if (!tmpconf->add_pports(kports)) { 2759 log_warnx("Error associating physical ports, " 2760 "continuing with old configuration"); 2761 } else { 2762 if (debug > 0) 2763 tmpconf->set_debug(debug); 2764 oldconf = std::move(newconf); 2765 newconf = std::move(tmpconf); 2766 2767 error = newconf->apply(oldconf.get()); 2768 if (error != 0) 2769 log_warnx("failed to reload " 2770 "configuration"); 2771 oldconf.reset(); 2772 } 2773 } else if (sigterm_received) { 2774 log_debugx("exiting on signal; " 2775 "reloading empty configuration"); 2776 2777 log_debugx("removing CTL iSCSI ports " 2778 "and terminating all connections"); 2779 2780 oldconf = std::move(newconf); 2781 newconf = std::make_unique<conf>(); 2782 if (debug > 0) 2783 newconf->set_debug(debug); 2784 error = newconf->apply(oldconf.get()); 2785 if (error != 0) 2786 log_warnx("failed to apply configuration"); 2787 oldconf.reset(); 2788 2789 log_warnx("exiting on signal"); 2790 return (0); 2791 } else { 2792 nchildren -= wait_for_children(false); 2793 assert(nchildren >= 0); 2794 if (timed_out()) { 2795 newconf->isns_update(); 2796 } 2797 } 2798 } 2799 /* NOTREACHED */ 2800 } 2801