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