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