Blame usr/iscsid.c

Packit Service 646995
/*
Packit Service 646995
 * iSCSI Initiator Daemon
Packit Service 646995
 *
Packit Service 646995
 * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman
Packit Service 646995
 * Copyright (C) 2006 Mike Christie
Packit Service 646995
 * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
Packit Service 646995
Packit Service 646995
 * maintained by open-iscsi@googlegroups.com
Packit Service 646995
 *
Packit Service 646995
 * This program is free software; you can redistribute it and/or modify
Packit Service 646995
 * it under the terms of the GNU General Public License as published
Packit Service 646995
 * by the Free Software Foundation; either version 2 of the License, or
Packit Service 646995
 * (at your option) any later version.
Packit Service 646995
 *
Packit Service 646995
 * This program is distributed in the hope that it will be useful, but
Packit Service 646995
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 646995
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Packit Service 646995
 * General Public License for more details.
Packit Service 646995
 *
Packit Service 646995
 * See the file COPYING included with this distribution for more details.
Packit Service 646995
 */
Packit Service 646995
#include <errno.h>
Packit Service 646995
#include <fcntl.h>
Packit Service 646995
#include <getopt.h>
Packit Service 646995
#include <stdlib.h>
Packit Service 646995
#include <stdio.h>
Packit Service 646995
#include <unistd.h>
Packit Service 646995
#include <string.h>
Packit Service 646995
#include <signal.h>
Packit Service 646995
#include <grp.h>
Packit Service 646995
#include <sys/mman.h>
Packit Service 646995
#include <sys/utsname.h>
Packit Service 646995
#include <sys/types.h>
Packit Service 646995
#include <sys/wait.h>
Packit Service 646995
#include <sys/types.h>
Packit Service 646995
#include <sys/stat.h>
Packit Service 646995
#ifndef	NO_SYSTEMD
Packit Service 646995
#include <systemd/sd-daemon.h>
Packit Service 646995
#endif
Packit Service 646995
Packit Service 646995
#include "iscsid.h"
Packit Service 646995
#include "mgmt_ipc.h"
Packit Service 646995
#include "event_poll.h"
Packit Service 646995
#include "iscsi_ipc.h"
Packit Service 646995
#include "log.h"
Packit Service 646995
#include "iscsi_util.h"
Packit Service 646995
#include "initiator.h"
Packit Service 646995
#include "transport.h"
Packit Service 646995
#include "idbm.h"
Packit Service 646995
#include "version.h"
Packit Service 646995
#include "iscsi_sysfs.h"
Packit Service 646995
#include "iface.h"
Packit Service 646995
#include "session_info.h"
Packit Service 646995
#include "sysdeps.h"
Packit Service 646995
#include "discoveryd.h"
Packit Service 646995
#include "iscsid_req.h"
Packit Service 646995
#include "iscsi_err.h"
Packit Service 646995
Packit Service 646995
/* global config info */
Packit Service 646995
struct iscsi_daemon_config daemon_config;
Packit Service 646995
struct iscsi_daemon_config *dconfig = &daemon_config;
Packit Service 646995
Packit Service 646995
static char program_name[] = "iscsid";
Packit Service 646995
static pid_t log_pid;
Packit Service 646995
static gid_t gid;
Packit Service 646995
static int daemonize = 1;
Packit Service 646995
static int mgmt_ipc_fd;
Packit Service 646995
static int sessions_to_recover = 0;
Packit Service 646995
Packit Service 646995
static struct option const long_options[] = {
Packit Service 646995
	{"config", required_argument, NULL, 'c'},
Packit Service 646995
	{"initiatorname", required_argument, NULL, 'i'},
Packit Service 646995
	{"foreground", no_argument, NULL, 'f'},
Packit Service 646995
	{"debug", required_argument, NULL, 'd'},
Packit Service 646995
	{"uid", required_argument, NULL, 'u'},
Packit Service 646995
	{"gid", required_argument, NULL, 'g'},
Packit Service 646995
	{"no-pid-file", no_argument, NULL, 'n'},
Packit Service 646995
	{"pid", required_argument, NULL, 'p'},
Packit Service 646995
	{"help", no_argument, NULL, 'h'},
Packit Service 646995
	{"version", no_argument, NULL, 'v'},
Packit Service 646995
	{NULL, 0, NULL, 0},
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
static void usage(int status)
Packit Service 646995
{
Packit Service 646995
	if (status != 0)
Packit Service 646995
		fprintf(stderr, "Try `%s --help' for more information.\n",
Packit Service 646995
			program_name);
Packit Service 646995
	else {
Packit Service 646995
		printf("Usage: %s [OPTION]\n", program_name);
Packit Service 646995
		printf("\
Packit Service 646995
Open-iSCSI initiator daemon.\n\
Packit Service 646995
  -c, --config=[path]     Execute in the config file (" CONFIG_FILE ").\n\
Packit Service 646995
  -i, --initiatorname=[path]     read initiatorname from file (" INITIATOR_NAME_FILE ").\n\
Packit Service 646995
  -f, --foreground        make the program run in the foreground\n\
Packit Service 646995
  -d, --debug debuglevel  print debugging information\n\
Packit Service 646995
  -u, --uid=uid           run as uid, default is current user\n\
Packit Service 646995
  -g, --gid=gid           run as gid, default is current user group\n\
Packit Service 646995
  -n, --no-pid-file       do not use a pid file\n\
Packit Service 646995
  -p, --pid=pidfile       use pid file (default " PID_FILE ").\n\
Packit Service 646995
  -h, --help              display this help and exit\n\
Packit Service 646995
  -v, --version           display version and exit\n\
Packit Service 646995
");
Packit Service 646995
	}
Packit Service 646995
	exit(status);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void
Packit Service 646995
setup_rec_from_negotiated_values(node_rec_t *rec, struct session_info *info)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_session_operational_config session_conf;
Packit Service 646995
	struct iscsi_conn_operational_config conn_conf;
Packit Service 646995
	struct iscsi_auth_config auth_conf;
Packit Service 646995
Packit Service 646995
	idbm_node_setup_from_conf(rec);
Packit Service 646995
	strlcpy(rec->name, info->targetname, TARGET_NAME_MAXLEN);
Packit Service 646995
	rec->conn[0].port = info->persistent_port;
Packit Service 646995
	strlcpy(rec->conn[0].address, info->persistent_address, NI_MAXHOST);
Packit Service 646995
	rec->tpgt = info->tpgt;
Packit Service 646995
Packit Service 646995
	iscsi_sysfs_get_negotiated_session_conf(info->sid, &session_conf);
Packit Service 646995
	iscsi_sysfs_get_negotiated_conn_conf(info->sid, &conn_conf);
Packit Service 646995
	iscsi_sysfs_get_auth_conf(info->sid, &auth_conf);
Packit Service 646995
Packit Service 646995
	if (strlen(auth_conf.username))
Packit Service 646995
		strcpy(rec->session.auth.username, auth_conf.username);
Packit Service 646995
Packit Service 646995
	if (strlen(auth_conf.username_in))
Packit Service 646995
		strcpy(rec->session.auth.username_in, auth_conf.username_in);
Packit Service 646995
Packit Service 646995
	if (strlen((char *)auth_conf.password)) {
Packit Service 646995
		strcpy((char *)rec->session.auth.password,
Packit Service 646995
			(char *)auth_conf.password);
Packit Service 646995
		rec->session.auth.password_length = auth_conf.password_length;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (strlen((char *)auth_conf.password_in)) {
Packit Service 646995
		strcpy((char *)rec->session.auth.password_in,
Packit Service 646995
			(char *)auth_conf.password_in);
Packit Service 646995
		rec->session.auth.password_in_length =
Packit Service 646995
						auth_conf.password_in_length;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (is_valid_operational_value(conn_conf.HeaderDigest)) {
Packit Service 646995
		if (conn_conf.HeaderDigest)
Packit Service 646995
			rec->conn[0].iscsi.HeaderDigest =
Packit Service 646995
						CONFIG_DIGEST_PREFER_ON;
Packit Service 646995
		else
Packit Service 646995
			rec->conn[0].iscsi.HeaderDigest =
Packit Service 646995
						CONFIG_DIGEST_PREFER_OFF;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (is_valid_operational_value(conn_conf.DataDigest)) {
Packit Service 646995
		if (conn_conf.DataDigest)
Packit Service 646995
			rec->conn[0].iscsi.DataDigest = CONFIG_DIGEST_PREFER_ON;
Packit Service 646995
		else
Packit Service 646995
			rec->conn[0].iscsi.DataDigest =
Packit Service 646995
						CONFIG_DIGEST_PREFER_OFF;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (is_valid_operational_value(conn_conf.MaxRecvDataSegmentLength))
Packit Service 646995
		rec->conn[0].iscsi.MaxRecvDataSegmentLength =
Packit Service 646995
					conn_conf.MaxRecvDataSegmentLength;
Packit Service 646995
Packit Service 646995
	if (is_valid_operational_value(conn_conf.MaxXmitDataSegmentLength))
Packit Service 646995
		 rec->conn[0].iscsi.MaxXmitDataSegmentLength =
Packit Service 646995
					conn_conf.MaxXmitDataSegmentLength;
Packit Service 646995
Packit Service 646995
	if (is_valid_operational_value(session_conf.FirstBurstLength))
Packit Service 646995
		rec->session.iscsi.FirstBurstLength =
Packit Service 646995
					session_conf.FirstBurstLength;
Packit Service 646995
Packit Service 646995
	if (is_valid_operational_value(session_conf.MaxBurstLength))
Packit Service 646995
		rec->session.iscsi.MaxBurstLength =
Packit Service 646995
					session_conf.MaxBurstLength;
Packit Service 646995
Packit Service 646995
	if (is_valid_operational_value(session_conf.ImmediateData)) {
Packit Service 646995
		if (session_conf.ImmediateData)
Packit Service 646995
			rec->session.iscsi.ImmediateData = 1;
Packit Service 646995
		else
Packit Service 646995
			rec->session.iscsi.ImmediateData = 0;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (is_valid_operational_value(session_conf.InitialR2T)) {
Packit Service 646995
		if (session_conf.InitialR2T)
Packit Service 646995
			rec->session.iscsi.InitialR2T = 0;
Packit Service 646995
		else
Packit Service 646995
			rec->session.iscsi.InitialR2T = 1;
Packit Service 646995
	}
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int sync_session(__attribute__((unused))void *data,
Packit Service 646995
			struct session_info *info)
Packit Service 646995
{
Packit Service 646995
	node_rec_t rec, sysfsrec;
Packit Service 646995
	iscsiadm_req_t req;
Packit Service 646995
	iscsiadm_rsp_t rsp;
Packit Service 646995
	struct iscsi_transport *t;
Packit Service 646995
	int rc, retries = 0;
Packit Service 646995
Packit Service 646995
	log_debug(7, "sync session [%d][%s,%s.%d][%s]", info->sid,
Packit Service 646995
		  info->targetname, info->persistent_address,
Packit Service 646995
		  info->port, info->iface.hwaddress);
Packit Service 646995
Packit Service 646995
	t = iscsi_sysfs_get_transport_by_sid(info->sid);
Packit Service 646995
	if (!t)
Packit Service 646995
		return 0;
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * Just rescan the device in case this is the first startup.
Packit Service 646995
	 * (TODO: should do this async and check for state).
Packit Service 646995
	 */
Packit Service 646995
	if (t->caps & CAP_FW_DB) {
Packit Service 646995
		uint32_t host_no;
Packit Service 646995
		int err;
Packit Service 646995
Packit Service 646995
		host_no = iscsi_sysfs_get_host_no_from_sid(info->sid, &err;;
Packit Service 646995
		if (err) {
Packit Service 646995
			log_error("Could not get host no from sid %u. Can not "
Packit Service 646995
				  "sync session: %s", info->sid,
Packit Service 646995
				  iscsi_err_to_str(err));
Packit Service 646995
			return 0;
Packit Service 646995
		}
Packit Service 646995
		iscsi_sysfs_scan_host(host_no, 0, idbm_session_autoscan(NULL));
Packit Service 646995
		return 0;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (!iscsi_sysfs_session_user_created(info->sid))
Packit Service 646995
		return 0;
Packit Service 646995
Packit Service 646995
	memset(&rec, 0, sizeof(node_rec_t));
Packit Service 646995
	/*
Packit Service 646995
	 * We might get the local ip address for software. We do not
Packit Service 646995
	 * want to try and bind a session by ip though.
Packit Service 646995
	 */
Packit Service 646995
	if (!t->template->set_host_ip)
Packit Service 646995
		memset(info->iface.ipaddress, 0, sizeof(info->iface.ipaddress));
Packit Service 646995
Packit Service 646995
	if (idbm_rec_read(&rec, info->targetname, info->tpgt,
Packit Service 646995
			  info->persistent_address, info->persistent_port,
Packit Service 646995
			  &info->iface, false)) {
Packit Service 646995
		log_warning("Could not read data from db. Using default and "
Packit Service 646995
			    "currently negotiated values");
Packit Service 646995
		setup_rec_from_negotiated_values(&rec, info);
Packit Service 646995
		iface_copy(&rec.iface, &info->iface);
Packit Service 646995
	} else {
Packit Service 646995
		/*
Packit Service 646995
		 * we have a valid record and iface so lets merge
Packit Service 646995
		 * the values from them and sysfs to try and get
Packit Service 646995
		 * the most uptodate values.
Packit Service 646995
		 *
Packit Service 646995
		 * Currenlty that means we will use the CHAP, target, portal
Packit Service 646995
		 * and iface values from sysfs and use timer, queue depth,
Packit Service 646995
		 * and segment length values from the record.
Packit Service 646995
		 */
Packit Service 646995
		memset(&sysfsrec, 0, sizeof(node_rec_t));
Packit Service 646995
		setup_rec_from_negotiated_values(&sysfsrec, info);
Packit Service 646995
		/*
Packit Service 646995
		 * target, portal and iface values have to be the same
Packit Service 646995
		 * or we would not have found the record, so just copy
Packit Service 646995
		 * CHAP settings.
Packit Service 646995
		 */
Packit Service 646995
		memcpy(&rec.session.auth, &sysfsrec.session.auth,
Packit Service 646995
		      sizeof(struct iscsi_auth_config));
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* multiple drivers could be connected to the same portal */
Packit Service 646995
	if (!iscsi_match_session(&rec, info))
Packit Service 646995
		return -1;
Packit Service 646995
	/*
Packit Service 646995
	 * We use the initiator name from sysfs because
Packit Service 646995
	 * the session could have come from our db or ibft or some other
Packit Service 646995
	 * app.
Packit Service 646995
	 */
Packit Service 646995
	strcpy(rec.iface.iname, info->iface.iname);
Packit Service 646995
	memset(&req, 0, sizeof(req));
Packit Service 646995
	req.command = MGMT_IPC_SESSION_SYNC;
Packit Service 646995
	req.u.session.sid = info->sid;
Packit Service 646995
	memcpy(&req.u.session.rec, &rec, sizeof(node_rec_t));
Packit Service 646995
Packit Service 646995
retry:
Packit Service 646995
	rc = iscsid_exec_req(&req, &rsp, 0, info->iscsid_req_tmo);
Packit Service 646995
	if (rc == ISCSI_ERR_ISCSID_NOTCONN && retries < 30) {
Packit Service 646995
		retries++;
Packit Service 646995
		sleep(1);
Packit Service 646995
		goto retry;
Packit Service 646995
	}
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static char *iscsid_get_config_file(void)
Packit Service 646995
{
Packit Service 646995
	return daemon_config.config_file;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void iscsid_shutdown(void)
Packit Service 646995
{
Packit Service 646995
	pid_t pid;
Packit Service 646995
Packit Service 646995
	killpg(gid, SIGTERM);
Packit Service 646995
	while ((pid = waitpid(0, NULL, 0) > 0))
Packit Service 646995
		log_debug(7, "cleaned up pid %d", pid);
Packit Service 646995
Packit Service 646995
	log_warning("iscsid shutting down.");
Packit Service 646995
	if (daemonize && log_pid >= 0) {
Packit Service 646995
		log_debug(1, "daemon stopping");
Packit Service 646995
		log_close(log_pid);
Packit Service 646995
	}
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void catch_signal(int signo)
Packit Service 646995
{
Packit Service 646995
	/*
Packit Service 646995
	 * Do not try to call log_debug() if there is a PIPE error
Packit Service 646995
	 * because we can get caught in a PIPE error loop.
Packit Service 646995
	 */
Packit Service 646995
	if (signo != SIGPIPE)
Packit Service 646995
		log_debug(1, "pid %d caught signal %d", getpid(), signo);
Packit Service 646995
Packit Service 646995
	/* In foreground mode, treat SIGINT like SIGTERM */
Packit Service 646995
	if (!daemonize && signo == SIGINT)
Packit Service 646995
		signo = SIGTERM;
Packit Service 646995
Packit Service 646995
	switch (signo) {
Packit Service 646995
	case SIGTERM:
Packit Service 646995
		event_loop_exit(NULL);
Packit Service 646995
		break;
Packit Service 646995
	default:
Packit Service 646995
		break;
Packit Service 646995
	}
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void missing_iname_warn(char *initiatorname_file)
Packit Service 646995
{
Packit Service 646995
	log_error("Warning: InitiatorName file %s does not exist or does not "
Packit Service 646995
		  "contain a properly formatted InitiatorName. If using "
Packit Service 646995
		  "software iscsi (iscsi_tcp or ib_iser) or partial offload "
Packit Service 646995
		  "(bnx2i or cxgbi iscsi), you may not be able to log "
Packit Service 646995
		  "into or discover targets. Please create a file %s that "
Packit Service 646995
		  "contains a sting with the format: InitiatorName="
Packit Service 646995
		  "iqn.yyyy-mm.<reversed domain name>[:identifier].\n\n"
Packit Service 646995
		  "Example: InitiatorName=iqn.2001-04.com.redhat:fc6.\n"
Packit Service 646995
		  "If using hardware iscsi like qla4xxx this message can be "
Packit Service 646995
		  "ignored.", initiatorname_file, initiatorname_file);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
/* called right before we enter the event loop */
Packit Service 646995
static void set_state_to_ready(void)
Packit Service 646995
{
Packit Service 646995
#ifndef	NO_SYSTEMD
Packit Service 646995
	if (sessions_to_recover)
Packit Service 646995
		sd_notify(0, "READY=1\n"
Packit Service 646995
				"RELOADING=1\n"
Packit Service 646995
				"STATUS=Syncing existing session(s)\n");
Packit Service 646995
	else
Packit Service 646995
		sd_notify(0, "READY=1\n"
Packit Service 646995
				"STATUS=Ready to process requests\n");
Packit Service 646995
#endif
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
/* called when recovery process has been reaped */
Packit Service 646995
static void set_state_done_reloading(void)
Packit Service 646995
{
Packit Service 646995
#ifndef	NO_SYSTEMD
Packit Service 646995
	sessions_to_recover = 0;
Packit Service 646995
	sd_notifyf(0, "READY=1\n"
Packit Service 646995
			"STATUS=Ready to process requests\n");
Packit Service 646995
#endif
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int main(int argc, char *argv[])
Packit Service 646995
{
Packit Service 646995
	struct utsname host_info; /* will use to compound initiator alias */
Packit Service 646995
	char *config_file = CONFIG_FILE;
Packit Service 646995
	char *initiatorname_file = INITIATOR_NAME_FILE;
Packit Service 646995
	char *pid_file = PID_FILE;
Packit Service 646995
	char *safe_logout;
Packit Service 646995
	int ch, longindex;
Packit Service 646995
	uid_t uid = 0;
Packit Service 646995
	struct sigaction sa_old;
Packit Service 646995
	struct sigaction sa_new;
Packit Service 646995
	int control_fd;
Packit Service 646995
	pid_t pid;
Packit Service 646995
Packit Service 646995
	while ((ch = getopt_long(argc, argv, "c:i:fd:nu:g:p:vh", long_options,
Packit Service 646995
				 &longindex)) >= 0) {
Packit Service 646995
		switch (ch) {
Packit Service 646995
		case 'c':
Packit Service 646995
			config_file = optarg;
Packit Service 646995
			break;
Packit Service 646995
		case 'i':
Packit Service 646995
			initiatorname_file = optarg;
Packit Service 646995
			break;
Packit Service 646995
		case 'f':
Packit Service 646995
			daemonize = 0;
Packit Service 646995
			break;
Packit Service 646995
		case 'd':
Packit Service 646995
			log_level = atoi(optarg);
Packit Service 646995
			break;
Packit Service 646995
		case 'u':
Packit Service 646995
			uid = strtoul(optarg, NULL, 10);
Packit Service 646995
			break;
Packit Service 646995
		case 'g':
Packit Service 646995
			gid = strtoul(optarg, NULL, 10);
Packit Service 646995
			break;
Packit Service 646995
		case 'n':
Packit Service 646995
			pid_file = NULL;
Packit Service 646995
			break;
Packit Service 646995
		case 'p':
Packit Service 646995
			pid_file = optarg;
Packit Service 646995
			break;
Packit Service 646995
		case 'v':
Packit Service 646995
			printf("%s version %s\n", program_name,
Packit Service 646995
				ISCSI_VERSION_STR);
Packit Service 646995
			exit(0);
Packit Service 646995
		case 'h':
Packit Service 646995
			usage(0);
Packit Service 646995
			break;
Packit Service 646995
		default:
Packit Service 646995
			usage(1);
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* initialize logger */
Packit Service 646995
	log_pid = log_init(program_name, DEFAULT_AREA_SIZE,
Packit Service 646995
		      daemonize ? log_do_log_daemon : log_do_log_std, NULL);
Packit Service 646995
	if (log_pid < 0)
Packit Service 646995
		exit(ISCSI_ERR);
Packit Service 646995
Packit Service 646995
	/* do not allow ctrl-c for now... */
Packit Service 646995
	sa_new.sa_handler = catch_signal;
Packit Service 646995
	sigemptyset(&sa_new.sa_mask);
Packit Service 646995
	sa_new.sa_flags = 0;
Packit Service 646995
	sigaction(SIGINT, &sa_new, &sa_old );
Packit Service 646995
	sigaction(SIGPIPE, &sa_new, &sa_old );
Packit Service 646995
	sigaction(SIGTERM, &sa_new, &sa_old );
Packit Service 646995
Packit Service 646995
	sysfs_init();
Packit Service 646995
	if (idbm_init(iscsid_get_config_file)) {
Packit Service 646995
		log_close(log_pid);
Packit Service 646995
		exit(ISCSI_ERR);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	umask(0177);
Packit Service 646995
Packit Service 646995
	mgmt_ipc_fd = -1;
Packit Service 646995
	control_fd = -1;
Packit Service 646995
	daemon_config.initiator_name = NULL;
Packit Service 646995
	daemon_config.initiator_alias = NULL;
Packit Service 646995
Packit Service 646995
	if ((mgmt_ipc_fd = mgmt_ipc_listen()) < 0) {
Packit Service 646995
		log_close(log_pid);
Packit Service 646995
		exit(ISCSI_ERR);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (daemonize) {
Packit Service 646995
		char buf[64];
Packit Service 646995
		int fd = -1;
Packit Service 646995
Packit Service 646995
		if (pid_file) {
Packit Service 646995
			fd = open(pid_file, O_WRONLY|O_CREAT, 0644);
Packit Service 646995
			if (fd < 0) {
Packit Service 646995
				log_error("Unable to create pid file");
Packit Service 646995
				log_close(log_pid);
Packit Service 646995
				exit(ISCSI_ERR);
Packit Service 646995
			}
Packit Service 646995
		}
Packit Service 646995
		pid = fork();
Packit Service 646995
		if (pid < 0) {
Packit Service 646995
			log_error("Starting daemon failed");
Packit Service 646995
			log_close(log_pid);
Packit Service 646995
			exit(ISCSI_ERR);
Packit Service 646995
		} else if (pid) {
Packit Service 646995
			log_info("iSCSI daemon with pid=%d started!", pid);
Packit Service 646995
			exit(0);
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		if (chdir("/") < 0)
Packit Service 646995
			log_debug(1, "Unable to chdir to /");
Packit Service 646995
		if (fd > 0) {
Packit Service 646995
			if (lockf(fd, F_TLOCK, 0) < 0) {
Packit Service 646995
				log_error("Unable to lock pid file");
Packit Service 646995
				log_close(log_pid);
Packit Service 646995
				exit(ISCSI_ERR);
Packit Service 646995
			}
Packit Service 646995
			if (ftruncate(fd, 0) < 0) {
Packit Service 646995
				log_error("Unable to truncate pid file");
Packit Service 646995
				log_close(log_pid);
Packit Service 646995
				exit(ISCSI_ERR);
Packit Service 646995
			}
Packit Service 646995
			sprintf(buf, "%d\n", getpid());
Packit Service 646995
			if (write(fd, buf, strlen(buf)) < 0) {
Packit Service 646995
				log_error("Unable to write pid file");
Packit Service 646995
				log_close(log_pid);
Packit Service 646995
				exit(ISCSI_ERR);
Packit Service 646995
			}
Packit Service 37be65
			close(fd);
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		if ((control_fd = ipc->ctldev_open()) < 0) {
Packit Service 646995
			log_close(log_pid);
Packit Service 646995
			exit(ISCSI_ERR);
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		daemon_init();
Packit Service 646995
	} else {
Packit Service 646995
		if ((control_fd = ipc->ctldev_open()) < 0) {
Packit Service 646995
			log_close(log_pid);
Packit Service 646995
			exit(1);
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (gid && setgid(gid) < 0) {
Packit Service 646995
		log_error("Unable to setgid to %d", gid);
Packit Service 646995
		log_close(log_pid);
Packit Service 646995
		exit(ISCSI_ERR);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if ((geteuid() == 0) && (getgroups(0, NULL))) {
Packit Service 646995
		if (setgroups(0, NULL) != 0) {
Packit Service 646995
			log_error("Unable to drop supplementary group ids");
Packit Service 646995
			log_close(log_pid);
Packit Service 646995
			exit(ISCSI_ERR);
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (uid && setuid(uid) < 0) {
Packit Service 646995
		log_error("Unable to setuid to %d", uid);
Packit Service 646995
		log_close(log_pid);
Packit Service 646995
		exit(ISCSI_ERR);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	memset(&daemon_config, 0, sizeof (daemon_config));
Packit Service 646995
	daemon_config.pid_file = pid_file;
Packit Service 646995
	daemon_config.config_file = config_file;
Packit Service 646995
	daemon_config.initiator_name = cfg_get_string_param(initiatorname_file,
Packit Service 646995
							    "InitiatorName");
Packit Service 646995
	if (daemon_config.initiator_name == NULL)
Packit Service 646995
		missing_iname_warn(initiatorname_file);
Packit Service 646995
Packit Service 646995
	/* optional InitiatorAlias */
Packit Service 646995
	daemon_config.initiator_alias =
Packit Service 646995
				cfg_get_string_param(initiatorname_file,
Packit Service 646995
						     "InitiatorAlias");
Packit Service 646995
	if (!daemon_config.initiator_alias) {
Packit Service 646995
		memset(&host_info, 0, sizeof (host_info));
Packit Service 646995
		if (uname(&host_info) >= 0) {
Packit Service 646995
			daemon_config.initiator_alias =
Packit Service 646995
				strdup(host_info.nodename);
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	log_debug(1, "InitiatorName=%s", daemon_config.initiator_name ?
Packit Service 646995
		 daemon_config.initiator_name : "NOT SET");
Packit Service 646995
	log_debug(1, "InitiatorAlias=%s", daemon_config.initiator_alias);
Packit Service 646995
Packit Service 646995
	safe_logout = cfg_get_string_param(config_file, "iscsid.safe_logout");
Packit Service 646995
	if (safe_logout && !strcmp(safe_logout, "Yes"))
Packit Service 646995
		daemon_config.safe_logout = 1;
Packit Service 646995
	free(safe_logout);
Packit Service 646995
Packit Service 646995
	/* see if we have any stale sessions to recover */
Packit Service 646995
	sessions_to_recover = iscsi_sysfs_count_sessions();
Packit Service 646995
	if (sessions_to_recover) {
Packit Service 646995
Packit Service 646995
		/*
Packit Service 646995
		 * recover stale sessions in the background
Packit Service 646995
		 */
Packit Service 646995
Packit Service 646995
		pid = fork();
Packit Service 646995
		if (pid == 0) {
Packit Service 646995
			int nr_found; /* not used */
Packit Service 646995
			/* child */
Packit Service 646995
			/* TODO - test with async support enabled */
Packit Service 646995
			iscsi_sysfs_for_each_session(NULL, &nr_found, sync_session, 0);
Packit Service 646995
			exit(0);
Packit Service 646995
		} else if (pid < 0) {
Packit Service 646995
			log_error("Fork failed error %d: existing sessions"
Packit Service 646995
				  " will not be synced", errno);
Packit Service 646995
		} else {
Packit Service 646995
			/* parent */
Packit Service 646995
			log_debug(8, "forked child (pid=%d) to recover %d session(s)",
Packit Service 646995
					(int)pid, sessions_to_recover);
Packit Service 646995
			reap_track_reload_process(pid, set_state_done_reloading);
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	iscsi_initiator_init();
Packit Service 646995
	increase_max_files();
Packit Service 646995
	discoveryd_start(daemon_config.initiator_name);
Packit Service 646995
Packit Service 646995
	/* oom-killer will not kill us at the night... */
Packit Service 646995
	if (oom_adjust())
Packit Service 646995
		log_debug(1, "can not adjust oom-killer's pardon");
Packit Service 646995
Packit Service 646995
	/* we don't want our active sessions to be paged out... */
Packit Service 646995
	if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
Packit Service 646995
		log_error("failed to mlockall, exiting...");
Packit Service 646995
		log_close(log_pid);
Packit Service 646995
		exit(ISCSI_ERR);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	set_state_to_ready();
Packit Service 646995
	event_loop(ipc, control_fd, mgmt_ipc_fd);
Packit Service 646995
Packit Service 646995
	idbm_terminate();
Packit Service 646995
	sysfs_cleanup();
Packit Service 646995
	ipc->ctldev_close();
Packit Service 646995
	mgmt_ipc_close(mgmt_ipc_fd);
Packit Service 646995
	if (daemon_config.initiator_name)
Packit Service 646995
		free(daemon_config.initiator_name);
Packit Service 646995
	if (daemon_config.initiator_alias)
Packit Service 646995
		free(daemon_config.initiator_alias);
Packit Service 646995
	free_initiator();
Packit Service 646995
	iscsid_shutdown();
Packit Service 646995
	return 0;
Packit Service 646995
}