Blame usr/iscsi_util.c

Packit Service 646995
/*
Packit Service 646995
 * Misc helpers
Packit Service 646995
 *
Packit Service 646995
 * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman
Packit Service 646995
 * Copyright (C) 2006 - 2010 Mike Christie
Packit Service 646995
 * Copyright (C) 2006 - 2010 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 <fcntl.h>
Packit Service 646995
#include <unistd.h>
Packit Service 646995
#include <stdlib.h>
Packit Service 646995
#include <stdio.h>
Packit Service 646995
#include <string.h>
Packit Service 646995
#include <errno.h>
Packit Service 646995
#include <ctype.h>
Packit Service 646995
#include <sys/socket.h>
Packit Service 646995
#include <sys/un.h>
Packit Service 646995
#include <sys/types.h>
Packit Service 646995
#include <sys/stat.h>
Packit Service 646995
#include <sys/resource.h>
Packit Service 646995
Packit Service 646995
#include "sysdeps.h"
Packit Service 646995
#include "log.h"
Packit Service 646995
#include "iscsi_settings.h"
Packit Service 646995
#include "iface.h"
Packit Service 646995
#include "session_info.h"
Packit Service 646995
#include "iscsi_util.h"
Packit Service 646995
Packit Service 646995
int setup_abstract_addr(struct sockaddr_un *addr, char *unix_sock_name)
Packit Service 646995
{
Packit Service 646995
	memset(addr, 0, sizeof(*addr));
Packit Service 646995
	addr->sun_family = AF_LOCAL;
Packit Service 646995
	strlcpy(addr->sun_path + 1, unix_sock_name, sizeof(addr->sun_path) - 1);
Packit Service 646995
	return offsetof(struct sockaddr_un, sun_path) +
Packit Service 646995
		strlen(addr->sun_path + 1) + 1;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
void daemon_init(void)
Packit Service 646995
{
Packit Service 646995
	int fd;
Packit Service 646995
Packit Service 646995
	fd = open("/dev/null", O_RDWR);
Packit Service 646995
	if (fd == -1) {
Packit Service 646995
		exit(-1);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	dup2(fd, 0);
Packit Service 646995
	dup2(fd, 1);
Packit Service 646995
	dup2(fd, 2);
Packit Service 646995
	setsid();
Packit Service 646995
	if (chdir("/") < 0)
Packit Service 646995
		log_debug(1, "Could not chdir to /: %s", strerror(errno));
Packit Service 646995
	close(fd);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
#define ISCSI_OOM_PATH_LEN 48
Packit Service 646995
Packit Service 646995
int oom_adjust(void)
Packit Service 646995
{
Packit Service 646995
	int fd;
Packit Service 646995
	char path[ISCSI_OOM_PATH_LEN];
Packit Service 646995
	struct stat statb;
Packit Service 646995
Packit Service 646995
	errno = 0;
Packit Service 646995
	if (nice(-10) == -1 && errno != 0)
Packit Service 646995
		log_debug(1, "Could not increase process priority: %s",
Packit Service 646995
			  strerror(errno));
Packit Service 646995
Packit Service 646995
	snprintf(path, ISCSI_OOM_PATH_LEN, "/proc/%d/oom_score_adj", getpid());
Packit Service 646995
	if (stat(path, &statb)) {
Packit Service 646995
		/* older kernel so use old oom_adj file */
Packit Service 646995
		snprintf(path, ISCSI_OOM_PATH_LEN, "/proc/%d/oom_adj",
Packit Service 646995
			 getpid());
Packit Service 646995
	}
Packit Service 646995
	fd = open(path, O_WRONLY);
Packit Service 646995
	if (fd < 0)
Packit Service 646995
		return -1;
Packit Service 646995
	if (write(fd, "-16", 3) < 0) /* for 2.6.11 */
Packit Service 646995
		log_debug(1, "Could not set oom score to -16: %s",
Packit Service 646995
			  strerror(errno));
Packit Service 646995
	if (write(fd, "-17", 3) < 0) /* for Andrea's patch */
Packit Service 646995
		log_debug(1, "Could not set oom score to -17: %s",
Packit Service 646995
			  strerror(errno));
Packit Service 646995
	close(fd);
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
char*
Packit Service 646995
str_to_ipport(char *str, int *port, int *tpgt)
Packit Service 646995
{
Packit Service 646995
	char *stpgt, *sport = str, *ip = str;
Packit Service 646995
Packit Service 646995
	if (!strchr(ip, '.')) {
Packit Service 646995
		if (*ip == '[') {
Packit Service 646995
			/* IPv6 with [] */
Packit Service 646995
			if (!(sport = strchr(ip, ']')))
Packit Service 646995
				return NULL;
Packit Service 646995
			*sport++ = '\0';
Packit Service 646995
			ip++;
Packit Service 646995
			str = sport;
Packit Service 646995
		} else {
Packit Service 646995
			/* hostname or ipv6 */
Packit Service 646995
			sport = strchr(ip, ':');
Packit Service 646995
			if (sport) {
Packit Service 646995
				if (strchr(sport + 1, ':'))
Packit Service 646995
					/* ipv6 */
Packit Service 646995
					sport = NULL;
Packit Service 646995
				else
Packit Service 646995
					/* hostname:port */
Packit Service 646995
					str = sport;
Packit Service 646995
			}
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if (sport && (sport = strchr(str, ':'))) {
Packit Service 646995
		*sport++ = '\0';
Packit Service 646995
		*port = strtoul(sport, NULL, 10);
Packit Service 646995
		str = sport;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if ((stpgt = strchr(str, ','))) {
Packit Service 646995
		*stpgt++ = '\0';
Packit Service 646995
		*tpgt = strtoul(stpgt, NULL, 10);
Packit Service 646995
	} else
Packit Service 646995
		*tpgt = PORTAL_GROUP_TAG_UNKNOWN;
Packit Service 646995
Packit Service 646995
	log_debug(2, "ip %s, port %d, tgpt %d", ip, *port, *tpgt);
Packit Service 646995
	return ip;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
#define ISCSI_MAX_FILES 16384
Packit Service 646995
Packit Service 646995
int increase_max_files(void)
Packit Service 646995
{
Packit Service 646995
	struct rlimit rl;
Packit Service 646995
	int err;
Packit Service 646995
Packit Service 646995
	err = getrlimit(RLIMIT_NOFILE, &rl);
Packit Service 646995
	if (err) {
Packit Service 646995
		log_debug(1, "Could not get file limit (err %d)", errno);
Packit Service 646995
		return errno;
Packit Service 646995
	}
Packit Service 646995
	log_debug(1, "Max file limits %lu %lu",
Packit Service 646995
		        (long unsigned)rl.rlim_cur,
Packit Service 646995
			(long unsigned)rl.rlim_max);
Packit Service 646995
Packit Service 646995
	if (rl.rlim_cur < ISCSI_MAX_FILES)
Packit Service 646995
		rl.rlim_cur = ISCSI_MAX_FILES;
Packit Service 646995
	if (rl.rlim_max < ISCSI_MAX_FILES)
Packit Service 646995
		rl.rlim_max = ISCSI_MAX_FILES;
Packit Service 646995
Packit Service 646995
	err = setrlimit(RLIMIT_NOFILE, &rl);
Packit Service 646995
	if (err) {
Packit Service 646995
		log_debug(1, "Could not set file limit to %lu/%lu (err %d)",
Packit Service 646995
			  (long unsigned)rl.rlim_cur,
Packit Service 646995
			  (long unsigned)rl.rlim_max, errno);
Packit Service 646995
		return errno;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
/*
Packit Service 646995
 * from linux kernel
Packit Service 646995
 */
Packit Service 646995
char *strstrip(char *s)
Packit Service 646995
{
Packit Service 646995
	size_t size;
Packit Service 646995
	char *end;
Packit Service 646995
Packit Service 646995
	size = strlen(s);
Packit Service 646995
	if (!size)
Packit Service 646995
		return s;
Packit Service 646995
Packit Service 646995
	end = s + size - 1;
Packit Service 646995
	while (end >= s && isspace(*end))
Packit Service 646995
		end--;
Packit Service 646995
	*(end + 1) = '\0';
Packit Service 646995
Packit Service 646995
	while (*s && isspace(*s))
Packit Service 646995
		s++;
Packit Service 646995
Packit Service 646995
	return s;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
/**
Packit Service 646995
 * cfg_get_string_param - return param value
Packit Service 646995
 * @pathname: pathname and filename of config file
Packit Service 646995
 * @key: param name
Packit Service 646995
 *
Packit Service 646995
 * Assumes the delim is a "=". "#" comments a line, but if
Packit Service 646995
 * the "#" is after the key= then it is a valid value.
Packit Service 646995
*/
Packit Service 646995
char *cfg_get_string_param(char *pathname, const char *key)
Packit Service 646995
{
Packit Service 646995
	FILE *f = NULL;
Packit Service 646995
	char *line, buffer[1024];
Packit Service 646995
	char *value = NULL, *param, *comment;
Packit Service 646995
Packit Service 646995
	if (!pathname) {
Packit Service 646995
		log_error("No pathname to load %s from", key);
Packit Service 646995
		return NULL;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if ((f = fopen(pathname, "r"))) {
Packit Service 646995
		while ((line = fgets(buffer, sizeof (buffer), f))) {
Packit Service 646995
			param = strstr(line, key);
Packit Service 646995
			if (!param)
Packit Service 646995
				continue;
Packit Service 646995
Packit Service 646995
			/* make sure it is not commented out */
Packit Service 646995
			comment = strchr(line, '#');
Packit Service 646995
			if (comment) {
Packit Service 646995
				if (comment < param)
Packit Service 646995
					continue;
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			param = strchr(param, '=');
Packit Service 646995
			if (!param) {
Packit Service 646995
				log_error("Invalid config line for %s. "
Packit Service 646995
					  "Missing '='.", key);
Packit Service 646995
				continue;
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			param++;
Packit Service 646995
			if (!strlen(param)) {
Packit Service 646995
				log_error("Invalid config line for %s. "
Packit Service 646995
					  "Missing value", key);
Packit Service 646995
				continue;
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			param = strstrip(param);
Packit Service 646995
			if (!strlen(param)) {
Packit Service 646995
				log_error("Invalid config line for %s. "
Packit Service 646995
					  "Missing value", key);
Packit Service 646995
				continue;
Packit Service 646995
			}
Packit Service 646995
Packit Service 646995
			value = strdup(param);
Packit Service 646995
			break;
Packit Service 646995
		}
Packit Service 646995
		fclose(f);
Packit Service 646995
		if (value)
Packit Service 646995
			log_debug(5, "%s=%s", key, value);
Packit Service 646995
	} else
Packit Service 646995
		log_error("can't open %s configuration file %s", key, pathname);
Packit Service 646995
Packit Service 646995
	return value;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
/**
Packit Service 646995
 * iscsi_addr_match - check if the addrs are to the same ip
Packit Service 646995
 * @address1: pattern
Packit Service 646995
 * @address2: address to check
Packit Service 646995
 *
Packit Service 646995
 * If address1 is blank then it matches any string passed in.
Packit Service 646995
 */
Packit Service 646995
static int iscsi_addr_match(char *address1, char *address2)
Packit Service 646995
{
Packit Service 646995
	struct addrinfo hints1, hints2, *res1, *res2;
Packit Service 646995
	int rc;
Packit Service 646995
Packit Service 646995
	if (!strlen(address1))
Packit Service 646995
		return 1;
Packit Service 646995
Packit Service 646995
	if (!strcmp(address1, address2))
Packit Service 646995
		return 1;
Packit Service 646995
Packit Service 646995
	memset(&hints1, 0, sizeof(struct addrinfo));
Packit Service 646995
	hints1.ai_family = AF_UNSPEC;
Packit Service 646995
	hints1.ai_socktype = SOCK_STREAM;
Packit Service 646995
Packit Service 646995
	memset(&hints2, 0, sizeof(struct addrinfo));
Packit Service 646995
	hints2.ai_family = AF_UNSPEC;
Packit Service 646995
	hints2.ai_socktype = SOCK_STREAM;
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * didn't match so we have to resolve to see if one is a dnsname
Packit Service 646995
	 * that matches an ip address.
Packit Service 646995
	 */
Packit Service 646995
	rc = getaddrinfo(address1, NULL, &hints1, &res1);
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_debug(1, "Match error. Could not resolve %s: %s", address1,
Packit Service 646995
			  gai_strerror(rc));
Packit Service 646995
		return 0;
Packit Service 646995
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = getaddrinfo(address2, NULL, &hints2, &res2);
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_debug(1, "Match error. Could not resolve %s: %s", address2,
Packit Service 646995
			  gai_strerror(rc));
Packit Service 646995
		rc = 0;
Packit Service 646995
		goto free_res1;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	if ((res1->ai_addrlen != res2->ai_addrlen) ||
Packit Service 646995
	    memcmp(res1->ai_addr, res2->ai_addr, res2->ai_addrlen))
Packit Service 646995
		rc = 0;
Packit Service 646995
	else
Packit Service 646995
		rc = 1;
Packit Service 646995
Packit Service 646995
	freeaddrinfo(res2);
Packit Service 646995
free_res1:
Packit Service 646995
	freeaddrinfo(res1);
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int __iscsi_match_session(node_rec_t *rec, char *targetname,
Packit Service 646995
			  char *address, int port, struct iface_rec *iface,
Packit Service 646995
			  unsigned sid)
Packit Service 646995
{
Packit Service 646995
	if (!rec) {
Packit Service 646995
		log_debug(6, "no rec info to match");
Packit Service 646995
		return 1;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	log_debug(6, "match session [%s,%s,%d][%s %s,%s,%s]:%u",
Packit Service 646995
		  rec->name, rec->conn[0].address, rec->conn[0].port,
Packit Service 646995
		  rec->iface.name, rec->iface.transport_name,
Packit Service 646995
		  rec->iface.hwaddress, rec->iface.ipaddress,
Packit Service 646995
		  rec->session.sid);
Packit Service 646995
Packit Service 646995
	if (iface)
Packit Service 646995
		log_debug(6, "to [%s,%s,%d][%s %s,%s,%s]:%u",
Packit Service 646995
			  targetname, address, port, iface->name,
Packit Service 646995
			  iface->transport_name, iface->hwaddress,
Packit Service 646995
			  iface->ipaddress, sid);
Packit Service 646995
Packit Service 646995
	if (rec->session.sid && sid && rec->session.sid != sid)
Packit Service 646995
		return 0;
Packit Service 646995
Packit Service 646995
	if (strlen(rec->name) && strcmp(rec->name, targetname))
Packit Service 646995
		return 0;
Packit Service 646995
Packit Service 646995
	if (!iscsi_addr_match(rec->conn[0].address, address))
Packit Service 646995
		return 0;
Packit Service 646995
Packit Service 646995
	if (rec->conn[0].port != -1 && port != rec->conn[0].port)
Packit Service 646995
		return 0;
Packit Service 646995
Packit Service 646995
	if (!iface_match(&rec->iface, iface))
Packit Service 646995
		return 0;
Packit Service 646995
Packit Service 646995
	return 1;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int iscsi_match_session(void *data, struct session_info *info)
Packit Service 646995
{
Packit Service 646995
	return __iscsi_match_session(data, info->targetname,
Packit Service 646995
				     info->persistent_address,
Packit Service 646995
				     info->persistent_port, &info->iface,
Packit Service 646995
				     info->sid);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int iscsi_match_session_count(void *data, struct session_info *info)
Packit Service 646995
{
Packit Service 646995
	/*
Packit Service 646995
	 * iscsi_sysfs_for_each_session expects:
Packit Service 646995
	 *   0==match -1==nomatch >0==error
Packit Service 646995
	 * but iscsi_match_session returns:
Packit Service 646995
	 *   1==match 0==nomatch
Packit Service 646995
	 */
Packit Service 646995
	if (iscsi_match_session(data, info))
Packit Service 646995
		return 0;
Packit Service 646995
	return -1;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int iscsi_match_target(void *data, struct session_info *info)
Packit Service 646995
{
Packit Service 646995
	return __iscsi_match_session(data, info->targetname,
Packit Service 646995
				     info->persistent_address,
Packit Service 646995
				     info->persistent_port, NULL,
Packit Service 646995
				     MATCH_ANY_SID);
Packit Service 646995
}