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
usage(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
conf()84 conf::conf()
85 {
86 conf_genctr = global_genctr++;
87 }
88
89 void
set_debug(int debug)90 conf::set_debug(int debug)
91 {
92 conf_debug = debug;
93 }
94
95 void
set_isns_period(int period)96 conf::set_isns_period(int period)
97 {
98 conf_isns_period = period;
99 }
100
101 void
set_isns_timeout(int timeout)102 conf::set_isns_timeout(int timeout)
103 {
104 conf_isns_timeout = timeout;
105 }
106
107 void
set_maxproc(int maxproc)108 conf::set_maxproc(int maxproc)
109 {
110 conf_maxproc = maxproc;
111 }
112
113 void
set_timeout(int timeout)114 conf::set_timeout(int timeout)
115 {
116 conf_timeout = timeout;
117 }
118
119 bool
set_pidfile_path(std::string_view path)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
open_pidfile(const char * path)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
add_proxy_portal(portal * portal)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 *
proxy_portal(int id)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
set_type(const char * str)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
set_type(auth_type type)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 *
find_auth(std::string_view user) const200 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
check_secret_length(const char * user,const char * secret,const char * secret_type)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
add_chap(const char * user,const char * secret)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
add_chap_mutual(const char * user,const char * secret,const char * user2,const char * secret2)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
add_host_nqn(std::string_view nqn)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
host_permitted(std::string_view nqn) const284 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
add_initiator_name(std::string_view name)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
initiator_permitted(std::string_view initiator_name) const301 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
parse(const char * portal)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
add_host_address(const char * address)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
add_initiator_portal(const char * portal)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
matches(const struct sockaddr * sa) const404 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
host_permitted(const struct sockaddr * sa) const436 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
initiator_permitted(const struct sockaddr * sa) const448 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 *
add_auth_group(const char * name)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 *
define_default_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
find_auth_group(std::string_view name)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
portal_group(struct conf * conf,std::string_view name)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 *
add_portal_group(const char * name)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 *
define_default_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 *
find_portal_group(std::string_view name)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 *
add_transport_group(const char * name)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 *
define_default_transport_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 *
find_transport_group(std::string_view name)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
is_dummy() const589 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
parse_addr_port(const char * address,const char * def_port)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
add_port(struct portal_group_port * port)649 portal_group::add_port(struct portal_group_port *port)
650 {
651 pg_ports.emplace(port->target()->name(), port);
652 }
653
654 void
remove_port(struct portal_group_port * port)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
options() const662 portal_group::options() const
663 {
664 return (freebsd::nvlist_up(nvlist_clone(pg_options.get())));
665 }
666
667 bool
add_option(const char * name,const char * value)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
set_discovery_auth_group(const char * ag_name)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
set_dscp(u_int dscp)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
set_foreign()704 portal_group::set_foreign()
705 {
706 pg_foreign = true;
707 }
708
709 void
set_kernel()710 portal_group::set_kernel()
711 {
712 pg_kernel = true;
713 }
714
715 bool
set_offload(const char * offload)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
set_pcp(u_int pcp)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
set_redirection(const char * addr)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
set_tag(uint16_t tag)757 portal_group::set_tag(uint16_t tag)
758 {
759 pg_tag = tag;
760 }
761
762 void
verify(struct conf * conf)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
reuse_socket(struct portal & newp)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
open_sockets(struct conf & oldconf)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
close_sockets()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
add_isns(const char * addr)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
connect()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
send_request(int s,struct isns_req req)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
isns_register_request(const char * hostname)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
isns_check_request(const char * hostname)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
isns_deregister_request(const char * hostname)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
isns_register_targets(struct isns * isns,struct conf * oldconf)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
isns_check(struct isns * isns)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
isns_deregister_targets(struct isns * isns)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
isns_schedule_update()1051 conf::isns_schedule_update()
1052 {
1053 if (!conf_isns.empty())
1054 start_timer((conf_isns_period + 2) / 3);
1055 }
1056
1057 void
isns_update()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
add_port(std::string & name,uint32_t ctl_port)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
has_port(std::string_view name)1081 kports::has_port(std::string_view name)
1082 {
1083 return (pports.count(std::string(name)) > 0);
1084 }
1085
1086 struct pport *
find_port(const std::string & name)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
port(struct target * target)1095 port::port(struct target *target) :
1096 p_target(target)
1097 {
1098 target->add_port(this);
1099 }
1100
1101 void
clear_references()1102 port::clear_references()
1103 {
1104 p_target->remove_port(this);
1105 }
1106
portal_group_port(struct target * target,struct portal_group * pg,auth_group_sp ag)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
portal_group_port(struct target * target,struct portal_group * pg,uint32_t ctl_port)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
is_dummy() const1123 portal_group_port::is_dummy() const
1124 {
1125 return (p_portal_group->is_dummy());
1126 }
1127
1128 void
clear_references()1129 portal_group_port::clear_references()
1130 {
1131 p_portal_group->remove_port(this);
1132 port::clear_references();
1133 }
1134
1135 bool
add_port(struct target * target,struct portal_group * pg,auth_group_sp ag)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
add_port(struct target * target,struct portal_group * pg,uint32_t ctl_port)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
add_port(struct target * target,struct pport * pp)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
add_port(struct kports & kports,struct target * target,int pp,int vp)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 *
find_port(std::string_view target) const1205 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 *
add_controller(const char * name)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 *
find_controller(std::string_view name)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
target(struct conf * conf,const char * keyword,std::string_view name)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 *
add_target(const char * name)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 *
find_target(std::string_view name)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
use_private_auth(const char * keyword)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
add_chap(const char * user,const char * secret)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
add_chap_mutual(const char * user,const char * secret,const char * user2,const char * secret2)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
add_lun(u_int id,const char * lun_label,const char * lun_name)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
set_alias(std::string_view alias)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
set_auth_group(const char * ag_name)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
set_auth_type(const char * type)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
add_physical_port(std::string_view pport)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
set_redirection(const char * addr)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 *
start_lun(u_int id,const char * lun_label,const char * lun_name)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
add_port(struct port * port)1440 target::add_port(struct port *port)
1441 {
1442 t_ports.push_back(port);
1443 }
1444
1445 void
remove_port(struct port * port)1446 target::remove_port(struct port *port)
1447 {
1448 t_ports.remove(port);
1449 }
1450
1451 void
remove_lun(struct lun * lun)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
verify()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
lun(struct conf * conf,std::string_view name)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 *
add_lun(const char * name)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
delete_target_luns(struct lun * lun)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 *
find_lun(std::string_view name)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
nvlist_replace_string(nvlist_t * nvl,const char * name,const char * value)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
options() const1525 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
add_option(const char * name,const char * value)1540 lun::add_option(const char *name, const char *value)
1541 {
1542 return (option_new(l_options.get(), name, value));
1543 }
1544
1545 bool
set_backend(std::string_view value)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
set_blocksize(size_t value)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
set_ctl_lun(uint32_t value)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
set_device_type(uint8_t device_type)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
set_device_type(const char * value)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
set_device_id(std::string_view value)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
set_path(std::string_view value)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
set_scsiname(std::string_view value)1652 lun::set_scsiname(std::string_view value)
1653 {
1654 l_scsiname = value;
1655 }
1656
1657 bool
set_serial(std::string_view value)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
set_size(uint64_t value)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
changed(const struct lun & newlun) const1685 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
option_new(nvlist_t * nvl,const char * name,const char * value)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
verify()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
verify()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
reuse_socket(struct portal & oldp)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
init_socket()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
reuse_portal_group_socket(struct portal & newp)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
apply(struct conf * oldconf)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 /*
1977 * Rename the pidfile if the pathname changes. On startup,
1978 * oldconf created via conf_new_from_kernel will not contain a
1979 * valid pidfile_path. On shutdown, the temporary newconf
1980 * will not contain a valid pidfile_path.
1981 */
1982 if (!oldconf->conf_pidfile_path.empty() &&
1983 !conf_pidfile_path.empty()) {
1984 if (oldconf->conf_pidfile_path != conf_pidfile_path) {
1985 /* pidfile has changed. rename it */
1986 log_debugx("moving pidfile to %s",
1987 conf_pidfile_path.c_str());
1988 if (rename(oldconf->conf_pidfile_path.c_str(),
1989 conf_pidfile_path.c_str()) != 0) {
1990 log_err(1, "renaming pidfile %s -> %s",
1991 oldconf->conf_pidfile_path.c_str(),
1992 conf_pidfile_path.c_str());
1993 }
1994 }
1995 }
1996
1997 /*
1998 * Go through the new portal groups, assigning tags or preserving old.
1999 */
2000 for (auto &kv : conf_portal_groups) {
2001 struct portal_group &newpg = *kv.second;
2002
2003 if (newpg.tag() != 0)
2004 continue;
2005 auto it = oldconf->conf_portal_groups.find(kv.first);
2006 if (it != oldconf->conf_portal_groups.end())
2007 newpg.set_tag(it->second->tag());
2008 else
2009 newpg.allocate_tag();
2010 }
2011 for (auto &kv : conf_transport_groups) {
2012 struct portal_group &newpg = *kv.second;
2013
2014 if (newpg.tag() != 0)
2015 continue;
2016 auto it = oldconf->conf_transport_groups.find(kv.first);
2017 if (it != oldconf->conf_transport_groups.end())
2018 newpg.set_tag(it->second->tag());
2019 else
2020 newpg.allocate_tag();
2021 }
2022
2023 /* Deregister on removed iSNS servers. */
2024 for (auto &kv : oldconf->conf_isns) {
2025 if (conf_isns.count(kv.first) == 0)
2026 oldconf->isns_deregister_targets(&kv.second);
2027 }
2028
2029 /*
2030 * XXX: If target or lun removal fails, we should somehow "move"
2031 * the old lun or target into this, so that subsequent
2032 * conf::apply() would try to remove them again. That would
2033 * be somewhat hairy, though, and lun deletion failures don't
2034 * really happen, so leave it as it is for now.
2035 */
2036 /*
2037 * First, remove any ports present in the old configuration
2038 * and missing in the new one.
2039 */
2040 for (const auto &kv : oldconf->conf_ports) {
2041 const std::string &name = kv.first;
2042 port *oldport = kv.second.get();
2043
2044 if (oldport->is_dummy())
2045 continue;
2046 const auto it = conf_ports.find(name);
2047 if (it != conf_ports.end() && !it->second->is_dummy())
2048 continue;
2049 log_debugx("removing port \"%s\"", name.c_str());
2050 if (!oldport->kernel_remove()) {
2051 log_warnx("failed to remove port %s", name.c_str());
2052 /*
2053 * XXX: Uncomment after fixing the root cause.
2054 *
2055 * cumulated_error++;
2056 */
2057 }
2058 }
2059
2060 /*
2061 * Second, remove any LUNs present in the old configuration
2062 * and missing in the new one.
2063 */
2064 for (auto it = oldconf->conf_luns.begin();
2065 it != oldconf->conf_luns.end(); ) {
2066 struct lun *oldlun = it->second.get();
2067
2068 auto newit = conf_luns.find(it->first);
2069 if (newit == conf_luns.end()) {
2070 log_debugx("lun \"%s\", CTL lun %d "
2071 "not found in new configuration; "
2072 "removing", oldlun->name(), oldlun->ctl_lun());
2073 if (!oldlun->kernel_remove()) {
2074 log_warnx("failed to remove lun \"%s\", "
2075 "CTL lun %d",
2076 oldlun->name(), oldlun->ctl_lun());
2077 cumulated_error++;
2078 }
2079 it++;
2080 continue;
2081 }
2082
2083 /*
2084 * Also remove the LUNs changed by more than size.
2085 */
2086 struct lun *newlun = newit->second.get();
2087 if (oldlun->changed(*newlun)) {
2088 if (!oldlun->kernel_remove()) {
2089 log_warnx("failed to remove lun \"%s\", "
2090 "CTL lun %d",
2091 oldlun->name(), oldlun->ctl_lun());
2092 cumulated_error++;
2093 }
2094
2095 /*
2096 * Delete the lun from the old configuration
2097 * so it is added as a new LUN below.
2098 */
2099 it = oldconf->conf_luns.erase(it);
2100 continue;
2101 }
2102
2103 newlun->set_ctl_lun(oldlun->ctl_lun());
2104 it++;
2105 }
2106
2107 for (auto it = conf_luns.begin(); it != conf_luns.end(); ) {
2108 struct lun *newlun = it->second.get();
2109
2110 auto oldit = oldconf->conf_luns.find(it->first);
2111 if (oldit != oldconf->conf_luns.end()) {
2112 log_debugx("modifying lun \"%s\", CTL lun %d",
2113 newlun->name(), newlun->ctl_lun());
2114 if (!newlun->kernel_modify()) {
2115 log_warnx("failed to "
2116 "modify lun \"%s\", CTL lun %d",
2117 newlun->name(), newlun->ctl_lun());
2118 cumulated_error++;
2119 }
2120 it++;
2121 continue;
2122 }
2123
2124 log_debugx("adding lun \"%s\"", newlun->name());
2125 if (!newlun->kernel_add()) {
2126 log_warnx("failed to add lun \"%s\"", newlun->name());
2127 delete_target_luns(newlun);
2128 it = conf_luns.erase(it);
2129 cumulated_error++;
2130 } else
2131 it++;
2132 }
2133
2134 /*
2135 * Now add new ports or modify existing ones.
2136 */
2137 for (auto it = conf_ports.begin(); it != conf_ports.end(); ) {
2138 const std::string &name = it->first;
2139 port *newport = it->second.get();
2140
2141 if (newport->is_dummy()) {
2142 it++;
2143 continue;
2144 }
2145 const auto oldit = oldconf->conf_ports.find(name);
2146 if (oldit == oldconf->conf_ports.end() ||
2147 oldit->second->is_dummy()) {
2148 log_debugx("adding port \"%s\"", name.c_str());
2149 if (!newport->kernel_add()) {
2150 log_warnx("failed to add port %s",
2151 name.c_str());
2152
2153 /*
2154 * XXX: Uncomment after fixing the
2155 * root cause.
2156 *
2157 * cumulated_error++;
2158 */
2159
2160 /*
2161 * conf "owns" the port, but other
2162 * objects contain pointers to this
2163 * port that must be removed before
2164 * deleting the port.
2165 */
2166 newport->clear_references();
2167 it = conf_ports.erase(it);
2168 } else
2169 it++;
2170 } else {
2171 log_debugx("updating port \"%s\"", name.c_str());
2172 if (!newport->kernel_update(oldit->second.get()))
2173 log_warnx("failed to update port %s",
2174 name.c_str());
2175 it++;
2176 }
2177 }
2178
2179 /*
2180 * Go through the new portals, opening the sockets as necessary.
2181 */
2182 for (auto &kv : conf_portal_groups) {
2183 cumulated_error += kv.second->open_sockets(*oldconf);
2184 }
2185 for (auto &kv : conf_transport_groups) {
2186 cumulated_error += kv.second->open_sockets(*oldconf);
2187 }
2188
2189 /*
2190 * Go through the no longer used sockets, closing them.
2191 */
2192 for (auto &kv : oldconf->conf_portal_groups) {
2193 kv.second->close_sockets();
2194 }
2195 for (auto &kv : oldconf->conf_transport_groups) {
2196 kv.second->close_sockets();
2197 }
2198
2199 /* (Re-)Register on remaining/new iSNS servers. */
2200 for (auto &kv : conf_isns) {
2201 auto it = oldconf->conf_isns.find(kv.first);
2202 if (it == oldconf->conf_isns.end())
2203 isns_register_targets(&kv.second, nullptr);
2204 else
2205 isns_register_targets(&kv.second, oldconf);
2206 }
2207
2208 isns_schedule_update();
2209
2210 return (cumulated_error);
2211 }
2212
2213 bool
timed_out(void)2214 timed_out(void)
2215 {
2216
2217 return (sigalrm_received);
2218 }
2219
2220 static void
sigalrm_handler_fatal(int dummy __unused)2221 sigalrm_handler_fatal(int dummy __unused)
2222 {
2223 /*
2224 * It would be easiest to just log an error and exit. We can't
2225 * do this, though, because log_errx() is not signal safe, since
2226 * it calls syslog(3). Instead, set a flag checked by pdu_send()
2227 * and pdu_receive(), to call log_errx() there. Should they fail
2228 * to notice, we'll exit here one second later.
2229 */
2230 if (sigalrm_received) {
2231 /*
2232 * Oh well. Just give up and quit.
2233 */
2234 _exit(2);
2235 }
2236
2237 sigalrm_received = true;
2238 }
2239
2240 static void
sigalrm_handler(int dummy __unused)2241 sigalrm_handler(int dummy __unused)
2242 {
2243
2244 sigalrm_received = true;
2245 }
2246
2247 void
stop_timer()2248 stop_timer()
2249 {
2250 struct itimerval itv;
2251 int error;
2252
2253 log_debugx("session timeout disabled");
2254 bzero(&itv, sizeof(itv));
2255 error = setitimer(ITIMER_REAL, &itv, NULL);
2256 if (error != 0)
2257 log_err(1, "setitimer");
2258 sigalrm_received = false;
2259 }
2260
2261 void
start_timer(int timeout,bool fatal)2262 start_timer(int timeout, bool fatal)
2263 {
2264 struct sigaction sa;
2265 struct itimerval itv;
2266 int error;
2267
2268 if (timeout <= 0) {
2269 stop_timer();
2270 return;
2271 }
2272
2273 sigalrm_received = false;
2274 bzero(&sa, sizeof(sa));
2275 if (fatal)
2276 sa.sa_handler = sigalrm_handler_fatal;
2277 else
2278 sa.sa_handler = sigalrm_handler;
2279 sigfillset(&sa.sa_mask);
2280 error = sigaction(SIGALRM, &sa, NULL);
2281 if (error != 0)
2282 log_err(1, "sigaction");
2283
2284 /*
2285 * First SIGALRM will arive after timeout seconds.
2286 * If we do nothing, another one will arrive a second later.
2287 */
2288 log_debugx("setting session timeout to %d seconds", timeout);
2289 bzero(&itv, sizeof(itv));
2290 itv.it_interval.tv_sec = 1;
2291 itv.it_value.tv_sec = timeout;
2292 error = setitimer(ITIMER_REAL, &itv, NULL);
2293 if (error != 0)
2294 log_err(1, "setitimer");
2295 }
2296
2297 static void
wait_for_children(bool block)2298 wait_for_children(bool block)
2299 {
2300 pid_t pid;
2301 int status;
2302
2303 /*
2304 * If "block" is true, wait for at least one process.
2305 */
2306 while (nchildren > 0) {
2307 if (block)
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 nchildren--;
2323
2324 block = false;
2325 }
2326 }
2327
2328 static void
handle_connection(struct portal * portal,freebsd::fd_up fd,const struct sockaddr * client_sa,bool dont_fork)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 wait_for_children(false);
2345
2346 while (conf->maxproc() > 0 && nchildren >= conf->maxproc()) {
2347 log_debugx("maxproc limit of %d child processes hit; "
2348 "waiting for child process to exit",
2349 conf->maxproc());
2350 wait_for_children(true);
2351 }
2352 log_debugx("incoming connection; forking child process #%d",
2353 nchildren);
2354 nchildren++;
2355 pid = fork();
2356 if (pid < 0)
2357 log_err(1, "fork");
2358 if (pid > 0)
2359 return;
2360 pidfile.close();
2361 }
2362
2363 error = getnameinfo(client_sa, client_sa->sa_len,
2364 host, sizeof(host), NULL, 0, NI_NUMERICHOST);
2365 if (error != 0)
2366 log_errx(1, "getnameinfo: %s", gai_strerror(error));
2367
2368 log_debugx("accepted connection from %s; portal group \"%s\"",
2369 host, pg->name());
2370 log_set_peer_addr(host);
2371 setproctitle("%s", host);
2372
2373 portal->handle_connection(std::move(fd), host, client_sa);
2374 log_debugx("nothing more to do; exiting");
2375 exit(0);
2376 }
2377
2378 static void
main_loop(bool dont_fork)2379 main_loop(bool dont_fork)
2380 {
2381 struct kevent kev;
2382 struct portal *portal;
2383 struct sockaddr_storage client_sa;
2384 socklen_t client_salen;
2385 #ifdef ICL_KERNEL_PROXY
2386 int connection_id;
2387 int portal_id;
2388 #endif
2389 int error, client_fd;
2390
2391 for (;;) {
2392 if (sighup_received || sigterm_received || timed_out())
2393 return;
2394
2395 #ifdef ICL_KERNEL_PROXY
2396 if (proxy_mode) {
2397 client_salen = sizeof(client_sa);
2398 kernel_accept(&connection_id, &portal_id,
2399 (struct sockaddr *)&client_sa, &client_salen);
2400 assert(client_salen >= client_sa.ss_len);
2401
2402 log_debugx("incoming connection, id %d, portal id %d",
2403 connection_id, portal_id);
2404 portal = conf->proxy_portal(portal_id);
2405 if (portal == nullptr)
2406 log_errx(1,
2407 "kernel returned invalid portal_id %d",
2408 portal_id);
2409
2410 handle_connection(portal, connection_id,
2411 (struct sockaddr *)&client_sa, dont_fork);
2412 } else {
2413 #endif
2414 assert(proxy_mode == false);
2415
2416 error = kevent(kqfd, NULL, 0, &kev, 1, NULL);
2417 if (error == -1) {
2418 if (errno == EINTR)
2419 return;
2420 log_err(1, "kevent");
2421 }
2422
2423 switch (kev.filter) {
2424 case EVFILT_READ:
2425 portal = reinterpret_cast<struct portal *>(kev.udata);
2426 assert(portal->socket() == (int)kev.ident);
2427
2428 client_salen = sizeof(client_sa);
2429 client_fd = accept(portal->socket(),
2430 (struct sockaddr *)&client_sa,
2431 &client_salen);
2432 if (client_fd < 0) {
2433 if (errno == ECONNABORTED)
2434 continue;
2435 log_err(1, "accept");
2436 }
2437 assert(client_salen >= client_sa.ss_len);
2438
2439 handle_connection(portal, client_fd,
2440 (struct sockaddr *)&client_sa, dont_fork);
2441 break;
2442 default:
2443 __assert_unreachable();
2444 }
2445 #ifdef ICL_KERNEL_PROXY
2446 }
2447 #endif
2448 }
2449 }
2450
2451 static void
sighup_handler(int dummy __unused)2452 sighup_handler(int dummy __unused)
2453 {
2454
2455 sighup_received = true;
2456 }
2457
2458 static void
sigterm_handler(int dummy __unused)2459 sigterm_handler(int dummy __unused)
2460 {
2461
2462 sigterm_received = true;
2463 }
2464
2465 static void
sigchld_handler(int dummy __unused)2466 sigchld_handler(int dummy __unused)
2467 {
2468
2469 /*
2470 * The only purpose of this handler is to make SIGCHLD
2471 * interrupt the ISCSIDWAIT ioctl(2), so we can call
2472 * wait_for_children().
2473 */
2474 }
2475
2476 static void
register_signals(void)2477 register_signals(void)
2478 {
2479 struct sigaction sa;
2480 int error;
2481
2482 bzero(&sa, sizeof(sa));
2483 sa.sa_handler = sighup_handler;
2484 sigfillset(&sa.sa_mask);
2485 error = sigaction(SIGHUP, &sa, NULL);
2486 if (error != 0)
2487 log_err(1, "sigaction");
2488
2489 sa.sa_handler = sigterm_handler;
2490 error = sigaction(SIGTERM, &sa, NULL);
2491 if (error != 0)
2492 log_err(1, "sigaction");
2493
2494 sa.sa_handler = sigterm_handler;
2495 error = sigaction(SIGINT, &sa, NULL);
2496 if (error != 0)
2497 log_err(1, "sigaction");
2498
2499 sa.sa_handler = sigchld_handler;
2500 error = sigaction(SIGCHLD, &sa, NULL);
2501 if (error != 0)
2502 log_err(1, "sigaction");
2503 }
2504
2505 static void
check_perms(const char * path)2506 check_perms(const char *path)
2507 {
2508 struct stat sb;
2509 int error;
2510
2511 error = stat(path, &sb);
2512 if (error != 0) {
2513 log_warn("stat");
2514 return;
2515 }
2516 if (sb.st_mode & S_IWOTH) {
2517 log_warnx("%s is world-writable", path);
2518 } else if (sb.st_mode & S_IROTH) {
2519 log_warnx("%s is world-readable", path);
2520 } else if (sb.st_mode & S_IXOTH) {
2521 /*
2522 * Ok, this one doesn't matter, but still do it,
2523 * just for consistency.
2524 */
2525 log_warnx("%s is world-executable", path);
2526 }
2527
2528 /*
2529 * XXX: Should we also check for owner != 0?
2530 */
2531 }
2532
2533 static conf_up
conf_new_from_file(const char * path,bool ucl)2534 conf_new_from_file(const char *path, bool ucl)
2535 {
2536 struct auth_group *ag;
2537 struct portal_group *pg;
2538 bool valid;
2539
2540 log_debugx("obtaining configuration from %s", path);
2541
2542 conf_up conf = std::make_unique<struct conf>();
2543
2544 ag = conf->add_auth_group("default");
2545 assert(ag != NULL);
2546
2547 ag = conf->add_auth_group("no-authentication");
2548 assert(ag != NULL);
2549 ag->set_type(auth_type::NO_AUTHENTICATION);
2550
2551 ag = conf->add_auth_group("no-access");
2552 assert(ag != NULL);
2553 ag->set_type(auth_type::DENY);
2554
2555 pg = conf->add_portal_group("default");
2556 assert(pg != NULL);
2557
2558 pg = conf->add_transport_group("default");
2559 assert(pg != NULL);
2560
2561 conf_start(conf.get());
2562 if (ucl)
2563 valid = uclparse_conf(path);
2564 else
2565 valid = parse_conf(path);
2566 conf_finish();
2567
2568 if (!valid) {
2569 conf.reset();
2570 return {};
2571 }
2572
2573 check_perms(path);
2574
2575 if (!conf->default_auth_group_defined()) {
2576 log_debugx("auth-group \"default\" not defined; "
2577 "going with defaults");
2578 ag = conf->find_auth_group("default").get();
2579 assert(ag != NULL);
2580 ag->set_type(auth_type::DENY);
2581 }
2582
2583 if (!conf->default_portal_group_defined()) {
2584 log_debugx("portal-group \"default\" not defined; "
2585 "going with defaults");
2586 pg = conf->find_portal_group("default");
2587 assert(pg != NULL);
2588 pg->add_default_portals();
2589 }
2590
2591 if (!conf->default_portal_group_defined()) {
2592 log_debugx("transport-group \"default\" not defined; "
2593 "going with defaults");
2594 pg = conf->find_transport_group("default");
2595 assert(pg != NULL);
2596 pg->add_default_portals();
2597 }
2598
2599 if (!conf->verify()) {
2600 conf.reset();
2601 return {};
2602 }
2603
2604 return (conf);
2605 }
2606
2607 /*
2608 * If the config file specifies physical ports for any target, associate them
2609 * with the config file. If necessary, create them.
2610 */
2611 bool
add_pports(struct kports & kports)2612 conf::add_pports(struct kports &kports)
2613 {
2614 struct pport *pp;
2615 int ret, i_pp, i_vp;
2616
2617 for (auto &kv : conf_targets) {
2618 struct target *targ = kv.second.get();
2619
2620 for (const auto &pport : targ->pports()) {
2621 ret = sscanf(pport.c_str(), "ioctl/%d/%d", &i_pp,
2622 &i_vp);
2623 if (ret > 0) {
2624 if (!add_port(kports, targ, i_pp, i_vp)) {
2625 log_warnx("can't create new ioctl port "
2626 "for %s", targ->label());
2627 return (false);
2628 }
2629
2630 continue;
2631 }
2632
2633 pp = kports.find_port(pport);
2634 if (pp == NULL) {
2635 log_warnx("unknown port \"%s\" for %s",
2636 pport.c_str(), targ->label());
2637 return (false);
2638 }
2639 if (pp->linked()) {
2640 log_warnx("can't link port \"%s\" to %s, "
2641 "port already linked to some target",
2642 pport.c_str(), targ->label());
2643 return (false);
2644 }
2645 if (!add_port(targ, pp)) {
2646 log_warnx("can't link port \"%s\" to %s",
2647 pport.c_str(), targ->label());
2648 return (false);
2649 }
2650 }
2651 }
2652 return (true);
2653 }
2654
2655 int
main(int argc,char ** argv)2656 main(int argc, char **argv)
2657 {
2658 struct kports kports;
2659 const char *config_path = DEFAULT_CONFIG_PATH;
2660 int debug = 0, ch, error;
2661 bool daemonize = true;
2662 bool test_config = false;
2663 bool use_ucl = false;
2664
2665 while ((ch = getopt(argc, argv, "dtuf:R")) != -1) {
2666 switch (ch) {
2667 case 'd':
2668 daemonize = false;
2669 debug++;
2670 break;
2671 case 't':
2672 test_config = true;
2673 break;
2674 case 'u':
2675 use_ucl = true;
2676 break;
2677 case 'f':
2678 config_path = optarg;
2679 break;
2680 case 'R':
2681 #ifndef ICL_KERNEL_PROXY
2682 log_errx(1, "ctld(8) compiled without ICL_KERNEL_PROXY "
2683 "does not support iSER protocol");
2684 #endif
2685 proxy_mode = true;
2686 break;
2687 case '?':
2688 default:
2689 usage();
2690 }
2691 }
2692 argc -= optind;
2693 if (argc != 0)
2694 usage();
2695
2696 log_init(debug);
2697 kernel_init();
2698
2699 conf_up newconf = conf_new_from_file(config_path, use_ucl);
2700
2701 if (newconf == NULL)
2702 log_errx(1, "configuration error; exiting");
2703
2704 if (test_config)
2705 return (0);
2706
2707 open_pidfile(newconf->pidfile_path());
2708
2709 register_signals();
2710
2711 conf_up oldconf = conf_new_from_kernel(kports);
2712
2713 if (debug > 0) {
2714 oldconf->set_debug(debug);
2715 newconf->set_debug(debug);
2716 }
2717
2718 if (!newconf->add_pports(kports))
2719 log_errx(1, "Error associating physical ports; exiting");
2720
2721 if (daemonize) {
2722 log_debugx("daemonizing");
2723 if (daemon(0, 0) == -1) {
2724 log_warn("cannot daemonize");
2725 return (1);
2726 }
2727 }
2728
2729 kqfd = kqueue();
2730 if (kqfd == -1) {
2731 log_warn("Cannot create kqueue");
2732 return (1);
2733 }
2734
2735 error = newconf->apply(oldconf.get());
2736 if (error != 0)
2737 log_errx(1, "failed to apply configuration; exiting");
2738
2739 oldconf.reset();
2740
2741 pidfile.write();
2742
2743 newconf->isns_schedule_update();
2744
2745 for (;;) {
2746 main_loop(!daemonize);
2747 if (sighup_received) {
2748 sighup_received = false;
2749 log_debugx("received SIGHUP, reloading configuration");
2750 conf_up tmpconf = conf_new_from_file(config_path,
2751 use_ucl);
2752
2753 if (tmpconf == NULL) {
2754 log_warnx("configuration error, "
2755 "continuing with old configuration");
2756 } else if (!tmpconf->add_pports(kports)) {
2757 log_warnx("Error associating physical ports, "
2758 "continuing with old configuration");
2759 } else {
2760 if (debug > 0)
2761 tmpconf->set_debug(debug);
2762 oldconf = std::move(newconf);
2763 newconf = std::move(tmpconf);
2764
2765 error = newconf->apply(oldconf.get());
2766 if (error != 0)
2767 log_warnx("failed to reload "
2768 "configuration");
2769 oldconf.reset();
2770 }
2771 } else if (sigterm_received) {
2772 log_debugx("exiting on signal; "
2773 "reloading empty configuration");
2774
2775 log_debugx("removing CTL iSCSI ports "
2776 "and terminating all connections");
2777
2778 oldconf = std::move(newconf);
2779 newconf = std::make_unique<conf>();
2780 if (debug > 0)
2781 newconf->set_debug(debug);
2782 error = newconf->apply(oldconf.get());
2783 if (error != 0)
2784 log_warnx("failed to apply configuration");
2785 oldconf.reset();
2786
2787 log_warnx("exiting on signal");
2788 return (0);
2789 } else {
2790 wait_for_children(false);
2791 if (timed_out()) {
2792 newconf->isns_update();
2793 }
2794 }
2795 }
2796 /* NOTREACHED */
2797 }
2798