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