1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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/cdefs.h>
33__FBSDID("$FreeBSD$");
34
35#include <sys/types.h>
36#include <sys/time.h>
37#include <sys/ioctl.h>
38#include <sys/param.h>
39#include <sys/linker.h>
40#include <sys/socket.h>
41#include <sys/capsicum.h>
42#include <sys/wait.h>
43#include <netinet/in.h>
44#include <assert.h>
45#include <capsicum_helpers.h>
46#include <errno.h>
47#include <fcntl.h>
48#include <libutil.h>
49#include <netdb.h>
50#include <signal.h>
51#include <stdbool.h>
52#include <stdint.h>
53#include <stdio.h>
54#include <stdlib.h>
55#include <string.h>
56#include <unistd.h>
57
58#include "iscsid.h"
59
60static volatile bool sigalrm_received = false;
61
62static int nchildren = 0;
63
64static void
65usage(void)
66{
67
68	fprintf(stderr, "usage: iscsid [-P pidfile][-d][-m maxproc][-t timeout]\n");
69	exit(1);
70}
71
72char *
73checked_strdup(const char *s)
74{
75	char *c;
76
77	c = strdup(s);
78	if (c == NULL)
79		log_err(1, "strdup");
80	return (c);
81}
82
83static void
84resolve_addr(const struct connection *conn, const char *address,
85    struct addrinfo **ai, bool initiator_side)
86{
87	struct addrinfo hints;
88	char *arg, *addr, *ch;
89	const char *port;
90	int error, colons = 0;
91
92	arg = checked_strdup(address);
93
94	if (arg[0] == '\0') {
95		fail(conn, "empty address");
96		log_errx(1, "empty address");
97	}
98	if (arg[0] == '[') {
99		/*
100		 * IPv6 address in square brackets, perhaps with port.
101		 */
102		arg++;
103		addr = strsep(&arg, "]");
104		if (arg == NULL) {
105			fail(conn, "malformed address");
106			log_errx(1, "malformed address %s", address);
107		}
108		if (arg[0] == '\0') {
109			port = NULL;
110		} else if (arg[0] == ':') {
111			port = arg + 1;
112		} else {
113			fail(conn, "malformed address");
114			log_errx(1, "malformed address %s", address);
115		}
116	} else {
117		/*
118		 * Either IPv6 address without brackets - and without
119		 * a port - or IPv4 address.  Just count the colons.
120		 */
121		for (ch = arg; *ch != '\0'; ch++) {
122			if (*ch == ':')
123				colons++;
124		}
125		if (colons > 1) {
126			addr = arg;
127			port = NULL;
128		} else {
129			addr = strsep(&arg, ":");
130			if (arg == NULL)
131				port = NULL;
132			else
133				port = arg;
134		}
135	}
136
137	if (port == NULL && !initiator_side)
138		port = "3260";
139
140	memset(&hints, 0, sizeof(hints));
141	hints.ai_family = PF_UNSPEC;
142	hints.ai_socktype = SOCK_STREAM;
143	hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
144	if (initiator_side)
145		hints.ai_flags |= AI_PASSIVE;
146
147	error = getaddrinfo(addr, port, &hints, ai);
148	if (error != 0) {
149		fail(conn, gai_strerror(error));
150		log_errx(1, "getaddrinfo for %s failed: %s",
151		    address, gai_strerror(error));
152	}
153
154	free(addr);
155}
156
157static struct connection *
158connection_new(int iscsi_fd, const struct iscsi_daemon_request *request)
159{
160	struct connection *conn;
161	struct iscsi_session_limits *isl;
162	struct addrinfo *from_ai, *to_ai;
163	const char *from_addr, *to_addr;
164#ifdef ICL_KERNEL_PROXY
165	struct iscsi_daemon_connect idc;
166#endif
167	int error, sockbuf;
168
169	conn = calloc(1, sizeof(*conn));
170	if (conn == NULL)
171		log_err(1, "calloc");
172
173	/*
174	 * Default values, from RFC 3720, section 12.
175	 */
176	conn->conn_protocol_level = 0;
177	conn->conn_header_digest = CONN_DIGEST_NONE;
178	conn->conn_data_digest = CONN_DIGEST_NONE;
179	conn->conn_initial_r2t = true;
180	conn->conn_immediate_data = true;
181	conn->conn_max_recv_data_segment_length = 8192;
182	conn->conn_max_send_data_segment_length = 8192;
183	conn->conn_max_burst_length = 262144;
184	conn->conn_first_burst_length = 65536;
185	conn->conn_iscsi_fd = iscsi_fd;
186
187	conn->conn_session_id = request->idr_session_id;
188	memcpy(&conn->conn_conf, &request->idr_conf, sizeof(conn->conn_conf));
189	memcpy(&conn->conn_isid, &request->idr_isid, sizeof(conn->conn_isid));
190	conn->conn_tsih = request->idr_tsih;
191
192	/*
193	 * Read the driver limits and provide reasonable defaults for the ones
194	 * the driver doesn't care about.  If a max_snd_dsl is not explicitly
195	 * provided by the driver then we'll make sure both conn->max_snd_dsl
196	 * and isl->max_snd_dsl are set to the rcv_dsl.  This preserves historic
197	 * behavior.
198	 */
199	isl = &conn->conn_limits;
200	memcpy(isl, &request->idr_limits, sizeof(*isl));
201	if (isl->isl_max_recv_data_segment_length == 0)
202		isl->isl_max_recv_data_segment_length = (1 << 24) - 1;
203	if (isl->isl_max_send_data_segment_length == 0)
204		isl->isl_max_send_data_segment_length =
205		    isl->isl_max_recv_data_segment_length;
206	if (isl->isl_max_burst_length == 0)
207		isl->isl_max_burst_length = (1 << 24) - 1;
208	if (isl->isl_first_burst_length == 0)
209		isl->isl_first_burst_length = (1 << 24) - 1;
210	if (isl->isl_first_burst_length > isl->isl_max_burst_length)
211		isl->isl_first_burst_length = isl->isl_max_burst_length;
212
213	/*
214	 * Limit default send length in case it won't be negotiated.
215	 * We can't do it for other limits, since they may affect both
216	 * sender and receiver operation, and we must obey defaults.
217	 */
218	if (conn->conn_max_send_data_segment_length >
219	    isl->isl_max_send_data_segment_length) {
220		conn->conn_max_send_data_segment_length =
221		    isl->isl_max_send_data_segment_length;
222	}
223
224	from_addr = conn->conn_conf.isc_initiator_addr;
225	to_addr = conn->conn_conf.isc_target_addr;
226
227	if (from_addr[0] != '\0')
228		resolve_addr(conn, from_addr, &from_ai, true);
229	else
230		from_ai = NULL;
231
232	resolve_addr(conn, to_addr, &to_ai, false);
233
234#ifdef ICL_KERNEL_PROXY
235	if (conn->conn_conf.isc_iser) {
236		memset(&idc, 0, sizeof(idc));
237		idc.idc_session_id = conn->conn_session_id;
238		if (conn->conn_conf.isc_iser)
239			idc.idc_iser = 1;
240		idc.idc_domain = to_ai->ai_family;
241		idc.idc_socktype = to_ai->ai_socktype;
242		idc.idc_protocol = to_ai->ai_protocol;
243		if (from_ai != NULL) {
244			idc.idc_from_addr = from_ai->ai_addr;
245			idc.idc_from_addrlen = from_ai->ai_addrlen;
246		}
247		idc.idc_to_addr = to_ai->ai_addr;
248		idc.idc_to_addrlen = to_ai->ai_addrlen;
249
250		log_debugx("connecting to %s using ICL kernel proxy", to_addr);
251		error = ioctl(iscsi_fd, ISCSIDCONNECT, &idc);
252		if (error != 0) {
253			fail(conn, strerror(errno));
254			log_err(1, "failed to connect to %s "
255			    "using ICL kernel proxy: ISCSIDCONNECT", to_addr);
256		}
257
258		if (from_ai != NULL)
259			freeaddrinfo(from_ai);
260		freeaddrinfo(to_ai);
261
262		return (conn);
263	}
264#endif /* ICL_KERNEL_PROXY */
265
266	if (conn->conn_conf.isc_iser) {
267		fail(conn, "iSER not supported");
268		log_errx(1, "iscsid(8) compiled without ICL_KERNEL_PROXY "
269		    "does not support iSER");
270	}
271
272	conn->conn_socket = socket(to_ai->ai_family, to_ai->ai_socktype,
273	    to_ai->ai_protocol);
274	if (conn->conn_socket < 0) {
275		fail(conn, strerror(errno));
276		log_err(1, "failed to create socket for %s", from_addr);
277	}
278	sockbuf = SOCKBUF_SIZE;
279	if (setsockopt(conn->conn_socket, SOL_SOCKET, SO_RCVBUF,
280	    &sockbuf, sizeof(sockbuf)) == -1)
281		log_warn("setsockopt(SO_RCVBUF) failed");
282	sockbuf = SOCKBUF_SIZE;
283	if (setsockopt(conn->conn_socket, SOL_SOCKET, SO_SNDBUF,
284	    &sockbuf, sizeof(sockbuf)) == -1)
285		log_warn("setsockopt(SO_SNDBUF) failed");
286	if (conn->conn_conf.isc_dscp != -1) {
287		int tos = conn->conn_conf.isc_dscp << 2;
288		if (to_ai->ai_family == AF_INET) {
289			if (setsockopt(conn->conn_socket,
290			    IPPROTO_IP, IP_TOS,
291			    &tos, sizeof(tos)) == -1)
292				log_warn("setsockopt(IP_TOS) "
293				    "failed for %s",
294				    from_addr);
295		} else
296		if (to_ai->ai_family == AF_INET6) {
297			if (setsockopt(conn->conn_socket,
298			    IPPROTO_IPV6, IPV6_TCLASS,
299			    &tos, sizeof(tos)) == -1)
300				log_warn("setsockopt(IPV6_TCLASS) "
301				    "failed for %s",
302				    from_addr);
303		}
304	}
305	if (conn->conn_conf.isc_pcp != -1) {
306		int pcp = conn->conn_conf.isc_pcp;
307		if (to_ai->ai_family == AF_INET) {
308			if (setsockopt(conn->conn_socket,
309			    IPPROTO_IP, IP_VLAN_PCP,
310			    &pcp, sizeof(pcp)) == -1)
311				log_warn("setsockopt(IP_VLAN_PCP) "
312				    "failed for %s",
313				    from_addr);
314		} else
315		if (to_ai->ai_family == AF_INET6) {
316			if (setsockopt(conn->conn_socket,
317			    IPPROTO_IPV6, IPV6_VLAN_PCP,
318			    &pcp, sizeof(pcp)) == -1)
319				log_warn("setsockopt(IPV6_VLAN_PCP) "
320				    "failed for %s",
321				    from_addr);
322		}
323	}
324	if (from_ai != NULL) {
325		error = bind(conn->conn_socket, from_ai->ai_addr,
326		    from_ai->ai_addrlen);
327		if (error != 0) {
328			fail(conn, strerror(errno));
329			log_err(1, "failed to bind to %s", from_addr);
330		}
331	}
332	log_debugx("connecting to %s", to_addr);
333	error = connect(conn->conn_socket, to_ai->ai_addr, to_ai->ai_addrlen);
334	if (error != 0) {
335		fail(conn, strerror(errno));
336		log_err(1, "failed to connect to %s", to_addr);
337	}
338
339	if (from_ai != NULL)
340		freeaddrinfo(from_ai);
341	freeaddrinfo(to_ai);
342
343	return (conn);
344}
345
346static void
347handoff(struct connection *conn)
348{
349	struct iscsi_daemon_handoff idh;
350	int error;
351
352	log_debugx("handing off connection to the kernel");
353
354	memset(&idh, 0, sizeof(idh));
355	idh.idh_session_id = conn->conn_session_id;
356	idh.idh_socket = conn->conn_socket;
357	strlcpy(idh.idh_target_alias, conn->conn_target_alias,
358	    sizeof(idh.idh_target_alias));
359	idh.idh_tsih = conn->conn_tsih;
360	idh.idh_statsn = conn->conn_statsn;
361	idh.idh_protocol_level = conn->conn_protocol_level;
362	idh.idh_header_digest = conn->conn_header_digest;
363	idh.idh_data_digest = conn->conn_data_digest;
364	idh.idh_initial_r2t = conn->conn_initial_r2t;
365	idh.idh_immediate_data = conn->conn_immediate_data;
366	idh.idh_max_recv_data_segment_length =
367	    conn->conn_max_recv_data_segment_length;
368	idh.idh_max_send_data_segment_length =
369	    conn->conn_max_send_data_segment_length;
370	idh.idh_max_burst_length = conn->conn_max_burst_length;
371	idh.idh_first_burst_length = conn->conn_first_burst_length;
372
373	error = ioctl(conn->conn_iscsi_fd, ISCSIDHANDOFF, &idh);
374	if (error != 0)
375		log_err(1, "ISCSIDHANDOFF");
376}
377
378void
379fail(const struct connection *conn, const char *reason)
380{
381	struct iscsi_daemon_fail idf;
382	int error, saved_errno;
383
384	saved_errno = errno;
385
386	memset(&idf, 0, sizeof(idf));
387	idf.idf_session_id = conn->conn_session_id;
388	strlcpy(idf.idf_reason, reason, sizeof(idf.idf_reason));
389
390	error = ioctl(conn->conn_iscsi_fd, ISCSIDFAIL, &idf);
391	if (error != 0)
392		log_err(1, "ISCSIDFAIL");
393
394	errno = saved_errno;
395}
396
397/*
398 * XXX: I CANT INTO LATIN
399 */
400static void
401capsicate(struct connection *conn)
402{
403	cap_rights_t rights;
404#ifdef ICL_KERNEL_PROXY
405	const unsigned long cmds[] = { ISCSIDCONNECT, ISCSIDSEND, ISCSIDRECEIVE,
406	    ISCSIDHANDOFF, ISCSIDFAIL, ISCSISADD, ISCSISREMOVE, ISCSISMODIFY };
407#else
408	const unsigned long cmds[] = { ISCSIDHANDOFF, ISCSIDFAIL, ISCSISADD,
409	    ISCSISREMOVE, ISCSISMODIFY };
410#endif
411
412	cap_rights_init(&rights, CAP_IOCTL);
413	if (caph_rights_limit(conn->conn_iscsi_fd, &rights) < 0)
414		log_err(1, "cap_rights_limit");
415
416	if (caph_ioctls_limit(conn->conn_iscsi_fd, cmds, nitems(cmds)) < 0)
417		log_err(1, "cap_ioctls_limit");
418
419	if (caph_enter() != 0)
420		log_err(1, "cap_enter");
421
422	if (cap_sandboxed())
423		log_debugx("Capsicum capability mode enabled");
424	else
425		log_warnx("Capsicum capability mode not supported");
426}
427
428bool
429timed_out(void)
430{
431
432	return (sigalrm_received);
433}
434
435static void
436sigalrm_handler(int dummy __unused)
437{
438	/*
439	 * It would be easiest to just log an error and exit.  We can't
440	 * do this, though, because log_errx() is not signal safe, since
441	 * it calls syslog(3).  Instead, set a flag checked by pdu_send()
442	 * and pdu_receive(), to call log_errx() there.  Should they fail
443	 * to notice, we'll exit here one second later.
444	 */
445	if (sigalrm_received) {
446		/*
447		 * Oh well.  Just give up and quit.
448		 */
449		_exit(2);
450	}
451
452	sigalrm_received = true;
453}
454
455static void
456set_timeout(int timeout)
457{
458	struct sigaction sa;
459	struct itimerval itv;
460	int error;
461
462	if (timeout <= 0) {
463		log_debugx("session timeout disabled");
464		return;
465	}
466
467	bzero(&sa, sizeof(sa));
468	sa.sa_handler = sigalrm_handler;
469	sigfillset(&sa.sa_mask);
470	error = sigaction(SIGALRM, &sa, NULL);
471	if (error != 0)
472		log_err(1, "sigaction");
473
474	/*
475	 * First SIGALRM will arive after conf_timeout seconds.
476	 * If we do nothing, another one will arrive a second later.
477	 */
478	bzero(&itv, sizeof(itv));
479	itv.it_interval.tv_sec = 1;
480	itv.it_value.tv_sec = timeout;
481
482	log_debugx("setting session timeout to %d seconds",
483	    timeout);
484	error = setitimer(ITIMER_REAL, &itv, NULL);
485	if (error != 0)
486		log_err(1, "setitimer");
487}
488
489static void
490sigchld_handler(int dummy __unused)
491{
492
493	/*
494	 * The only purpose of this handler is to make SIGCHLD
495	 * interrupt the ISCSIDWAIT ioctl(2), so we can call
496	 * wait_for_children().
497	 */
498}
499
500static void
501register_sigchld(void)
502{
503	struct sigaction sa;
504	int error;
505
506	bzero(&sa, sizeof(sa));
507	sa.sa_handler = sigchld_handler;
508	sigfillset(&sa.sa_mask);
509	error = sigaction(SIGCHLD, &sa, NULL);
510	if (error != 0)
511		log_err(1, "sigaction");
512
513}
514
515static void
516handle_request(int iscsi_fd, const struct iscsi_daemon_request *request, int timeout)
517{
518	struct connection *conn;
519
520	log_set_peer_addr(request->idr_conf.isc_target_addr);
521	if (request->idr_conf.isc_target[0] != '\0') {
522		log_set_peer_name(request->idr_conf.isc_target);
523		setproctitle("%s (%s)", request->idr_conf.isc_target_addr, request->idr_conf.isc_target);
524	} else {
525		setproctitle("%s", request->idr_conf.isc_target_addr);
526	}
527
528	conn = connection_new(iscsi_fd, request);
529	set_timeout(timeout);
530	capsicate(conn);
531	login(conn);
532	if (conn->conn_conf.isc_discovery != 0)
533		discovery(conn);
534	else
535		handoff(conn);
536
537	log_debugx("nothing more to do; exiting");
538	exit (0);
539}
540
541static int
542wait_for_children(bool block)
543{
544	pid_t pid;
545	int status;
546	int num = 0;
547
548	for (;;) {
549		/*
550		 * If "block" is true, wait for at least one process.
551		 */
552		if (block && num == 0)
553			pid = wait4(-1, &status, 0, NULL);
554		else
555			pid = wait4(-1, &status, WNOHANG, NULL);
556		if (pid <= 0)
557			break;
558		if (WIFSIGNALED(status)) {
559			log_warnx("child process %d terminated with signal %d",
560			    pid, WTERMSIG(status));
561		} else if (WEXITSTATUS(status) != 0) {
562			log_warnx("child process %d terminated with exit status %d",
563			    pid, WEXITSTATUS(status));
564		} else {
565			log_debugx("child process %d terminated gracefully", pid);
566		}
567		num++;
568	}
569
570	return (num);
571}
572
573int
574main(int argc, char **argv)
575{
576	int ch, debug = 0, error, iscsi_fd, maxproc = 30, retval, saved_errno,
577	    timeout = 60;
578	bool dont_daemonize = false;
579	struct pidfh *pidfh;
580	pid_t pid, otherpid;
581	const char *pidfile_path = DEFAULT_PIDFILE;
582	struct iscsi_daemon_request request;
583
584	while ((ch = getopt(argc, argv, "P:dl:m:t:")) != -1) {
585		switch (ch) {
586		case 'P':
587			pidfile_path = optarg;
588			break;
589		case 'd':
590			dont_daemonize = true;
591			debug++;
592			break;
593		case 'l':
594			debug = atoi(optarg);
595			break;
596		case 'm':
597			maxproc = atoi(optarg);
598			break;
599		case 't':
600			timeout = atoi(optarg);
601			break;
602		case '?':
603		default:
604			usage();
605		}
606	}
607	argc -= optind;
608	if (argc != 0)
609		usage();
610
611	log_init(debug);
612
613	pidfh = pidfile_open(pidfile_path, 0600, &otherpid);
614	if (pidfh == NULL) {
615		if (errno == EEXIST)
616			log_errx(1, "daemon already running, pid: %jd.",
617			    (intmax_t)otherpid);
618		log_err(1, "cannot open or create pidfile \"%s\"",
619		    pidfile_path);
620	}
621
622	iscsi_fd = open(ISCSI_PATH, O_RDWR);
623	if (iscsi_fd < 0 && errno == ENOENT) {
624		saved_errno = errno;
625		retval = kldload("iscsi");
626		if (retval != -1)
627			iscsi_fd = open(ISCSI_PATH, O_RDWR);
628		else
629			errno = saved_errno;
630	}
631	if (iscsi_fd < 0)
632		log_err(1, "failed to open %s", ISCSI_PATH);
633
634	if (dont_daemonize == false) {
635		if (daemon(0, 0) == -1) {
636			log_warn("cannot daemonize");
637			pidfile_remove(pidfh);
638			exit(1);
639		}
640	}
641
642	pidfile_write(pidfh);
643
644	register_sigchld();
645
646	for (;;) {
647		log_debugx("waiting for request from the kernel");
648
649		memset(&request, 0, sizeof(request));
650		error = ioctl(iscsi_fd, ISCSIDWAIT, &request);
651		if (error != 0) {
652			if (errno == EINTR) {
653				nchildren -= wait_for_children(false);
654				assert(nchildren >= 0);
655				continue;
656			}
657
658			log_err(1, "ISCSIDWAIT");
659		}
660
661		if (dont_daemonize) {
662			log_debugx("not forking due to -d flag; "
663			    "will exit after servicing a single request");
664		} else {
665			nchildren -= wait_for_children(false);
666			assert(nchildren >= 0);
667
668			while (maxproc > 0 && nchildren >= maxproc) {
669				log_debugx("maxproc limit of %d child processes hit; "
670				    "waiting for child process to exit", maxproc);
671				nchildren -= wait_for_children(true);
672				assert(nchildren >= 0);
673			}
674			log_debugx("incoming connection; forking child process #%d",
675			    nchildren);
676			nchildren++;
677
678			pid = fork();
679			if (pid < 0)
680				log_err(1, "fork");
681			if (pid > 0)
682				continue;
683		}
684
685		pidfile_close(pidfh);
686		handle_request(iscsi_fd, &request, timeout);
687	}
688
689	return (0);
690}
691