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