Blame usr/iscsistart.c

Packit Service 646995
/*
Packit Service 646995
 * iSCSI Root Boot Program based on daemon code
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
 * 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 <ctype.h>
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 <time.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
Packit Service 646995
#include "initiator.h"
Packit Service 646995
#include "iscsi_ipc.h"
Packit Service 646995
#include "event_poll.h"
Packit Service 646995
#include "transport.h"
Packit Service 646995
#include "log.h"
Packit Service 646995
#include "iscsi_util.h"
Packit Service 646995
#include "idbm.h"
Packit Service 646995
#include "idbm_fields.h"
Packit Service 646995
#include "version.h"
Packit Service 646995
#include "iscsi_sysfs.h"
Packit Service 646995
#include "iscsi_settings.h"
Packit Service 646995
#include "fw_context.h"
Packit Service 646995
#include "iface.h"
Packit Service 646995
#include "sysdeps.h"
Packit Service 646995
#include "iscsid_req.h"
Packit Service 646995
#include "iscsi_err.h"
Packit Service 646995
#include "iface.h"
Packit Service 646995
Packit Service 646995
/* global config info */
Packit Service 646995
/* initiator needs initiator name/alias */
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 node_rec_t config_rec;
Packit Service 646995
static LIST_HEAD(targets);
Packit Service 646995
static LIST_HEAD(user_params);
Packit Service 646995
Packit Service 646995
static char program_name[] = "iscsistart";
Packit Service 646995
Packit Service 646995
/* used by initiator */
Packit Service 646995
extern struct iscsi_ipc *ipc;
Packit Service 646995
Packit Service 646995
static struct option const long_options[] = {
Packit Service 646995
	{"initiatorname", required_argument, NULL, 'i'},
Packit Service 646995
	{"targetname", required_argument, NULL, 't'},
Packit Service 646995
	{"tgpt", required_argument, NULL, 'g'},
Packit Service 646995
	{"address", required_argument, NULL, 'a'},
Packit Service 646995
	{"port", required_argument, NULL, 'p'},
Packit Service 646995
	{"username", required_argument, NULL, 'u'},
Packit Service 646995
	{"password", required_argument, NULL, 'w'},
Packit Service 646995
	{"username_in", required_argument, NULL, 'U'},
Packit Service 646995
	{"password_in", required_argument, NULL, 'W'},
Packit Service 646995
	{"debug", required_argument, NULL, 'd'},
Packit Service 646995
	{"fwparam_connect", no_argument, NULL, 'b'},
Packit Service 646995
	{"fwparam_network", no_argument, NULL, 'N'},
Packit Service 646995
	{"fwparam_print", no_argument, NULL, 'f'},
Packit Service 646995
	{"param", 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.\n\
Packit Service 646995
  -i, --initiatorname=name set InitiatorName to name (Required)\n\
Packit Service 646995
  -t, --targetname=name    set TargetName to name (Required)\n\
Packit Service 646995
  -g, --tgpt=N             set target portal group tag to N (Required)\n\
Packit Service 646995
  -a, --address=A.B.C.D    set IP address to A.B.C.D (Required)\n\
Packit Service 646995
  -p, --port=N             set port to N (Default 3260)\n\
Packit Service 646995
  -u, --username=N         set username to N (optional)\n\
Packit Service 646995
  -w, --password=N         set password to N (optional\n\
Packit Service 646995
  -U, --username_in=N      set incoming username to N (optional)\n\
Packit Service 646995
  -W, --password_in=N      set incoming password to N (optional)\n\
Packit Service 646995
  -d, --debug=debuglevel   print debugging information \n\
Packit Service 646995
  -b, --fwparam_connect    create a session to the target using iBFT or OF\n\
Packit Service 646995
  -N, --fwparam_network    bring up the network as specified by iBFT or OF\n\
Packit Service 646995
  -f, --fwparam_print      print the iBFT or OF info to STDOUT \n\
Packit Service 646995
  -P, --param=NAME=VALUE   set parameter with the name NAME to VALUE\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 int stop_event_loop(void)
Packit Service 646995
{
Packit Service 646995
	iscsiadm_req_t req;
Packit Service 646995
	iscsiadm_rsp_t rsp;
Packit Service 646995
	int rc;
Packit Service 646995
Packit Service 646995
	memset(&req, 0, sizeof(req));
Packit Service 646995
	req.command = MGMT_IPC_IMMEDIATE_STOP;
Packit Service 646995
	rc = iscsid_exec_req(&req, &rsp, 0, -1);
Packit Service 646995
	if (rc) {
Packit Service 646995
		iscsi_err_print_msg(rc);
Packit Service 646995
		log_error("Could not stop event_loop");
Packit Service 646995
	}
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int apply_params(struct node_rec *rec)
Packit Service 646995
{
Packit Service 646995
	struct user_param *param;
Packit Service 646995
	int rc;
Packit Service 646995
Packit Service 646995
	/* Must init this so we can check if user overrode them */
Packit Service 646995
	rec->session.initial_login_retry_max = -1;
Packit Service 646995
	rec->conn[0].timeo.noop_out_interval = -1;
Packit Service 646995
	rec->conn[0].timeo.noop_out_timeout = -1;
Packit Service 646995
	rec->session.scan = -1;
Packit Service 646995
Packit Service 646995
	list_for_each_entry(param, &user_params, list) {
Packit Service 646995
		/*
Packit Service 646995
		 * user may not have passed in all params that were set by
Packit Service 646995
		 * ibft/iscsi_boot, so clear out values that might conflict
Packit Service 646995
		 * with user overrides
Packit Service 646995
		 */
Packit Service 646995
		if (!strcmp(param->name, IFACE_NETNAME)) {
Packit Service 646995
			/* overriding netname so MAC will be for old netdev */
Packit Service 646995
			memset(rec->iface.hwaddress, 0,
Packit Service 646995
				sizeof(rec->iface.hwaddress));
Packit Service 646995
		} else if (!strcmp(param->name, IFACE_HWADDR)) {
Packit Service 646995
			/* overriding MAC so netdev will be for old MAC */
Packit Service 646995
			memset(rec->iface.netdev, 0, sizeof(rec->iface.netdev));
Packit Service 646995
		} else if (!strcmp(param->name, IFACE_TRANSPORTNAME)) {
Packit Service 646995
			/*
Packit Service 646995
			 * switching drivers so all old binding info is no
Packit Service 646995
			 * longer valid. Old values were either for offload
Packit Service 646995
			 * and we are switching to software or the reverse,
Packit Service 646995
			 * or switching types of cards (bnx2i to cxgb3i).
Packit Service 646995
			 */
Packit Service 646995
			memset(&rec->iface, 0, sizeof(rec->iface));
Packit Service 646995
			iface_setup_defaults(&rec->iface);
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = idbm_node_set_rec_from_param(&user_params, rec, 0);
Packit Service 646995
	if (rc)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * For root boot we could not change this in older versions so
Packit Service 646995
	 * if user did not override then use the defaults.
Packit Service 646995
	 *
Packit Service 646995
	 * Increase to account for boot using static setup.
Packit Service 646995
	 */
Packit Service 646995
	if (rec->session.initial_login_retry_max == -1)
Packit Service 646995
		rec->session.initial_login_retry_max = 30;
Packit Service 646995
	/* we used to not be able to answer so turn off */
Packit Service 646995
	if (rec->conn[0].timeo.noop_out_interval == -1)
Packit Service 646995
		rec->conn[0].timeo.noop_out_interval = 0;
Packit Service 646995
	if (rec->conn[0].timeo.noop_out_timeout == -1)
Packit Service 646995
		rec->conn[0].timeo.noop_out_timeout = 0;
Packit Service 646995
	if (rec->session.scan == -1)
Packit Service 646995
		rec->session.scan = DEF_INITIAL_SCAN;
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int parse_param(char *param_str)
Packit Service 646995
{
Packit Service 646995
	struct user_param *param;
Packit Service 646995
	char *name, *value;
Packit Service 646995
Packit Service 646995
	name = param_str;
Packit Service 646995
Packit Service 646995
	value = strchr(param_str, '=');
Packit Service 646995
	if (!value) {
Packit Service 646995
		log_error("Invalid --param %s. Missing value.", param_str);
Packit Service 646995
		return ISCSI_ERR_INVAL;
Packit Service 646995
	}
Packit Service 646995
	*value = '\0';
Packit Service 646995
Packit Service 646995
	value++;
Packit Service 646995
	if (!strlen(value)) {
Packit Service 646995
		log_error("Invalid --param %s. Missing value.", param_str);
Packit Service 646995
		return ISCSI_ERR_INVAL;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	param = idbm_alloc_user_param(name, value);
Packit Service 646995
	if (!param) {
Packit Service 646995
		log_error("Could not allocate memory for param.");
Packit Service 646995
		return ISCSI_ERR_NOMEM;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	list_add(&param->list, &user_params);
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int login_session(struct node_rec *rec)
Packit Service 646995
{
Packit Service 646995
	iscsiadm_req_t req;
Packit Service 646995
	iscsiadm_rsp_t rsp;
Packit Service 646995
	int rc, msec, err;
Packit Service 646995
	struct timespec ts;
Packit Service 646995
Packit Service 646995
	rc = apply_params(rec);
Packit Service 646995
	if (rc)
Packit Service 646995
		return rc;
Packit Service 646995
Packit Service 646995
	printf("%s: Logging into %s %s:%d,%d\n", program_name, rec->name,
Packit Service 646995
		rec->conn[0].address, rec->conn[0].port,
Packit Service 646995
		rec->tpgt);
Packit Service 646995
	memset(&req, 0, sizeof(req));
Packit Service 646995
	req.command = MGMT_IPC_SESSION_LOGIN;
Packit Service 646995
	memcpy(&req.u.session.rec, rec, sizeof(*rec));
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * Need to handle race where iscsid proc is starting up while we are
Packit Service 646995
	 * trying to connect. Retry with exponential backoff, start from 50 ms.
Packit Service 646995
	 */
Packit Service 646995
	for (msec = 50; msec <= 15000; msec <<= 1) {
Packit Service 646995
		rc = iscsid_exec_req(&req, &rsp, 0, ISCSID_REQ_TIMEOUT);
Packit Service 646995
		if (rc == 0) {
Packit Service 646995
			return rc;
Packit Service 646995
		} else if (rc == ISCSI_ERR_ISCSID_NOTCONN) {
Packit Service 646995
			ts.tv_sec = msec / 1000;
Packit Service 646995
			ts.tv_nsec = (msec % 1000) * 1000000L;
Packit Service 646995
Packit Service 646995
			/* On EINTR, retry nanosleep with remaining time. */
Packit Service 646995
			while ((err = nanosleep(&ts, &ts)) < 0 &&
Packit Service 646995
			       errno == EINTR);
Packit Service 646995
			if (err < 0)
Packit Service 646995
				break;
Packit Service 646995
		} else {
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	iscsi_err_print_msg(rc);
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int setup_session(void)
Packit Service 646995
{
Packit Service 646995
	struct boot_context *context;
Packit Service 646995
	int rc = 0, rc2 = 0;
Packit Service 646995
Packit Service 646995
	if (list_empty(&targets))
Packit Service 646995
		return login_session(&config_rec);
Packit Service 646995
Packit Service 646995
	list_for_each_entry(context, &targets, list) {
Packit Service 646995
		struct node_rec *rec;
Packit Service 646995
Packit Service 646995
		rec = idbm_create_rec_from_boot_context(context);
Packit Service 646995
		if (!rec) {
Packit Service 646995
			log_error("Could not allocate memory. Could "
Packit Service 646995
				  "not start boot session to "
Packit Service 646995
				  "%s,%s,%d", context->targetname,
Packit Service 646995
				  context->target_ipaddr,
Packit Service 646995
				  context->target_port);
Packit Service 646995
			continue;
Packit Service 646995
		}
Packit Service 646995
Packit Service 646995
		rc2 = login_session(rec);
Packit Service 646995
		if (rc2)
Packit Service 646995
			rc = rc2;
Packit Service 646995
		free(rec);
Packit Service 646995
	}
Packit Service 646995
	fw_free_targets(&targets;;
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int session_in_use(__attribute__((unused))int sid)
Packit Service 646995
{
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static void catch_signal(int signo)
Packit Service 646995
{
Packit Service 646995
	log_warning("pid %d caught signal -%d", getpid(), signo);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
static int check_params(char *initiatorname)
Packit Service 646995
{
Packit Service 646995
	if (!initiatorname) {
Packit Service 646995
		log_error("InitiatorName not set. Exiting %s", program_name);
Packit Service 646995
		return EINVAL;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (config_rec.tpgt == PORTAL_GROUP_TAG_UNKNOWN) {
Packit Service 646995
		log_error("Portal Group not set. Exiting %s", program_name);
Packit Service 646995
		return EINVAL;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (!strlen(config_rec.name)) {
Packit Service 646995
		log_error("TargetName not set. Exiting %s", program_name);
Packit Service 646995
		return EINVAL;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (!strlen(config_rec.conn[0].address)) {
Packit Service 646995
		log_error("IP Address not set. Exiting %s", program_name);
Packit Service 646995
		return EINVAL;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
#define check_str_param_len(str, max_len, param)			\
Packit Service 646995
do {									\
Packit Service 646995
	if (strlen(str) > max_len) {					\
Packit Service 646995
		printf("%s: invalid %s %s. Max %s length is %d.\n",	\
Packit Service 646995
			program_name, param, str, param, max_len);	\
Packit Service 646995
		exit(ISCSI_ERR_INVAL);					\
Packit Service 646995
	}								\
Packit Service 646995
} while (0);
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
	struct iscsi_auth_config *auth;
Packit Service 646995
	char *initiatorname = NULL;
Packit Service 646995
	int ch, longindex, ret;
Packit Service 646995
	struct boot_context *context, boot_context;
Packit Service 646995
	struct sigaction sa_old;
Packit Service 646995
	struct sigaction sa_new;
Packit Service 646995
	int control_fd, mgmt_ipc_fd, err;
Packit Service 646995
	pid_t pid;
Packit Service 646995
Packit Service 646995
	idbm_node_setup_defaults(&config_rec);
Packit Service 646995
	config_rec.name[0] = '\0';
Packit Service 646995
	config_rec.conn[0].address[0] = '\0';
Packit Service 646995
	auth = &config_rec.session.auth;
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
Packit Service 646995
	/* initialize logger */
Packit Service 646995
	log_init(program_name, DEFAULT_AREA_SIZE, log_do_log_std, NULL);
Packit Service 646995
Packit Service 646995
	sysfs_init();
Packit Service 646995
Packit Service 646995
	while ((ch = getopt_long(argc, argv, "P:i:t:g:a:p:d:u:w:U:W:bNfvh",
Packit Service 646995
				 long_options, &longindex)) >= 0) {
Packit Service 646995
		switch (ch) {
Packit Service 646995
		case 'i':
Packit Service 646995
			initiatorname = optarg;
Packit Service 646995
			break;
Packit Service 646995
		case 't':
Packit Service 646995
			check_str_param_len(optarg, TARGET_NAME_MAXLEN,
Packit Service 646995
					    "targetname");
Packit Service 646995
			strlcpy(config_rec.name, optarg, TARGET_NAME_MAXLEN);
Packit Service 646995
			break;
Packit Service 646995
		case 'g':
Packit Service 646995
			config_rec.tpgt = atoi(optarg);
Packit Service 646995
			break;
Packit Service 646995
		case 'a':
Packit Service 646995
			check_str_param_len(optarg, NI_MAXHOST, "address");
Packit Service 646995
			strlcpy(config_rec.conn[0].address, optarg, NI_MAXHOST);
Packit Service 646995
			break;
Packit Service 646995
		case 'p':
Packit Service 646995
			config_rec.conn[0].port = atoi(optarg);
Packit Service 646995
			break;
Packit Service 646995
		case 'w':
Packit Service 646995
			check_str_param_len(optarg, AUTH_STR_MAX_LEN,
Packit Service 646995
					   "password");
Packit Service 646995
			strlcpy((char *)auth->password, optarg,
Packit Service 646995
				AUTH_STR_MAX_LEN);
Packit Service 646995
			auth->password_length = strlen((char *)auth->password);
Packit Service 646995
			break;
Packit Service 646995
		case 'W':
Packit Service 646995
			check_str_param_len(optarg, AUTH_STR_MAX_LEN,
Packit Service 646995
					   "password_in");
Packit Service 646995
			strlcpy((char *)auth->password_in, optarg,
Packit Service 646995
				AUTH_STR_MAX_LEN);
Packit Service 646995
			auth->password_in_length =
Packit Service 646995
				strlen((char *)auth->password_in);
Packit Service 646995
			break;
Packit Service 646995
		case 'u':
Packit Service 646995
			check_str_param_len(optarg, AUTH_STR_MAX_LEN,
Packit Service 646995
					    "username");
Packit Service 646995
			strlcpy(auth->username, optarg, AUTH_STR_MAX_LEN);
Packit Service 646995
			break;
Packit Service 646995
		case 'U':
Packit Service 646995
			check_str_param_len(optarg, AUTH_STR_MAX_LEN,
Packit Service 646995
					    "username_in");
Packit Service 646995
			strlcpy(auth->username_in, optarg, AUTH_STR_MAX_LEN);
Packit Service 646995
			break;
Packit Service 646995
		case 'd':
Packit Service 646995
			log_level = atoi(optarg);
Packit Service 646995
			break;
Packit Service 646995
		case 'b':
Packit Service 646995
			memset(&boot_context, 0, sizeof(boot_context));
Packit Service 646995
			ret = fw_get_entry(&boot_context);
Packit Service 646995
			if (ret) {
Packit Service 646995
				printf("Could not get boot entry.\n");
Packit Service 646995
				exit(ret);
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			initiatorname = boot_context.initiatorname;
Packit Service 646995
			ret = fw_get_targets(&targets;;
Packit Service 646995
			if (ret || list_empty(&targets)) {
Packit Service 646995
				printf("Could not setup fw entries.\n");
Packit Service 646995
				exit(ret);
Packit Service 646995
			}
Packit Service 646995
			break;
Packit Service 646995
		case 'N':
Packit Service 646995
			exit(fw_setup_nics());
Packit Service 646995
		case 'f':
Packit Service 646995
			ret = fw_get_targets(&targets;;
Packit Service 646995
			if (ret || list_empty(&targets)) {
Packit Service 646995
				printf("Could not get list of targets from "
Packit Service 646995
				       "firmware.\n");
Packit Service 646995
				exit(ret);
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			list_for_each_entry(context, &targets, list)
Packit Service 646995
				fw_print_entry(context);
Packit Service 646995
Packit Service 646995
			fw_free_targets(&targets;;
Packit Service 646995
			exit(0);
Packit Service 646995
		case 'P':
Packit Service 646995
			err = parse_param(optarg);
Packit Service 646995
			if (err)
Packit Service 646995
				exit(err);
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(ISCSI_ERR_INVAL);
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (list_empty(&targets) && check_params(initiatorname))
Packit Service 646995
		exit(ISCSI_ERR_INVAL);
Packit Service 646995
Packit Service 646995
	pid = fork();
Packit Service 646995
	if (pid < 0) {
Packit Service 646995
		log_error("iscsiboot fork failed");
Packit Service 646995
		exit(ISCSI_ERR_NOMEM);
Packit Service 646995
	} else if (pid) {
Packit Service 646995
		int status, rc, rc2;
Packit Service 646995
Packit Service 646995
		/* make a special socket path for only this iscsistart instance */
Packit Service 646995
		iscsid_set_namespace(pid);
Packit Service 646995
		sleep(1);
Packit Service 646995
Packit Service 646995
		rc = setup_session();
Packit Service 646995
		rc2 = stop_event_loop();
Packit Service 646995
		/*
Packit Service 646995
		 * something horrible happened. kill child and get
Packit Service 646995
		 * out of here
Packit Service 646995
		 */
Packit Service 646995
		if (rc2)
Packit Service 646995
			kill(pid, SIGTERM);
Packit Service 646995
Packit Service 646995
		waitpid(pid, &status, WUNTRACED);
Packit Service 646995
		if (rc || rc2)
Packit Service 646995
			exit(ISCSI_ERR);
Packit Service 646995
Packit Service 646995
		log_debug(1, "iscsi parent done");
Packit Service 646995
		exit(0);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	pid = getpid();
Packit Service 646995
	iscsid_set_namespace(pid);
Packit Service 646995
Packit Service 646995
	mgmt_ipc_fd = mgmt_ipc_listen();
Packit Service 646995
	if (mgmt_ipc_fd  < 0) {
Packit Service 646995
		log_error("Could not setup mgmt ipc");
Packit Service 646995
		exit(ISCSI_ERR_NOMEM);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	control_fd = ipc->ctldev_open();
Packit Service 646995
	if (control_fd < 0)
Packit Service 646995
		exit(ISCSI_ERR_NOMEM);
Packit Service 646995
Packit Service 646995
	memset(&daemon_config, 0, sizeof (daemon_config));
Packit Service 646995
	daemon_config.initiator_name = initiatorname;
Packit Service 646995
	/* optional InitiatorAlias */
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 = host_info.nodename;
Packit Service 646995
Packit Service 646995
	log_debug(1, "InitiatorName=%s", daemon_config.initiator_name);
Packit Service 646995
	log_debug(1, "InitiatorAlias=%s", daemon_config.initiator_alias);
Packit Service 646995
	log_debug(1, "TargetName=%s", config_rec.name);
Packit Service 646995
	log_debug(1, "TPGT=%d", config_rec.tpgt);
Packit Service 646995
	log_debug(1, "IP Address=%s", config_rec.conn[0].address);
Packit Service 646995
Packit Service 646995
	/* log the version, so that we can tell if the daemon and kernel module
Packit Service 646995
	 * match based on what shows up in the syslog.  Tarballs releases
Packit Service 646995
	 * always install both, but Linux distributors may put the kernel module
Packit Service 646995
	 * in a different RPM from the daemon and utils, and users may try to
Packit Service 646995
	 * mix and match in ways that don't work.
Packit Service 646995
	 */
Packit Service 646995
	log_error("version %s", ISCSI_VERSION_STR);
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
	/*
Packit Service 646995
	 * Start Main Event Loop
Packit Service 646995
	 */
Packit Service 646995
	iscsi_initiator_init();
Packit Service 646995
	event_loop(ipc, control_fd, mgmt_ipc_fd);
Packit Service 646995
	ipc->ctldev_close();
Packit Service 646995
	mgmt_ipc_close(mgmt_ipc_fd);
Packit Service 646995
	free_initiator();
Packit Service 646995
	sysfs_cleanup();
Packit Service 646995
Packit Service 646995
	log_debug(1, "iscsi child done");
Packit Service 646995
	return 0;
Packit Service 646995
}