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