⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isns.c

📁 Ubuntu公司提供免费的iSCSI Target
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * iSNS functions * * Copyright (C) 2006 FUJITA Tomonori <tomof@acm.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */#include <errno.h>#include <netdb.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <netinet/in.h>#include <netinet/tcp.h>#include <sys/socket.h>#include <sys/types.h>#include "iscsid.h"#include "isns_proto.h"#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))#define BUFSIZE (1 << 18)struct isns_io {	char *buf;	int offset;};struct isns_qry_mgmt {	char name[ISCSI_NAME_LEN];	uint16_t transaction;	struct qelem qlist;};struct isns_initiator {	char name[ISCSI_NAME_LEN];	struct qelem ilist;};static LIST_HEAD(qry_list);static uint16_t scn_listen_port;static int use_isns, use_isns_ac, isns_fd, scn_listen_fd, scn_fd;static struct isns_io isns_rx, scn_rx;static char *rxbuf;static uint16_t transaction;static uint32_t current_timeout = 30; /* seconds */static char eid[ISCSI_NAME_LEN];static uint8_t ip[16]; /* IET supoprts only one portal */static struct sockaddr_storage ss;int isns_scn_access(uint32_t tid, int fd, char *name){	struct isns_initiator *ini;	struct target *target = target_find_by_id(tid);	if (!use_isns || !use_isns_ac)		return 0;	if (!target)		return -EPERM;	list_for_each_entry(ini, &target->isns_head, ilist) {		if (!strcmp(ini->name, name))			return 0;	}	return -EPERM;}static int isns_get_ip(int fd){	int err, i;	uint32_t addr;	struct sockaddr_storage lss;	socklen_t slen = sizeof(lss);	err = getsockname(fd, (struct sockaddr *) &lss, &slen);	if (err) {		log_error("getsockname error %s!", gai_strerror(err));		return err;	}	err = getnameinfo((struct sockaddr *) &lss, sizeof(lss),			  eid, sizeof(eid), NULL, 0, 0);	if (err) {		log_error("getaddrinfo error %s!", gai_strerror(err));		return err;	}	switch (lss.ss_family) {	case AF_INET:		addr = (((struct sockaddr_in *) &lss)->sin_addr.s_addr);		ip[10] = ip[11] = 0xff;		ip[15] = 0xff & (addr >> 24);		ip[14] = 0xff & (addr >> 16);		ip[13] = 0xff & (addr >> 8);		ip[12] = 0xff & addr;		break;	case AF_INET6:		for (i = 0; i < ARRAY_SIZE(ip); i++)			ip[i] = ((struct sockaddr_in6 *) &lss)->sin6_addr.s6_addr[i];		break;	}	return 0;}static int isns_connect(void){	int fd, err;	fd = socket(ss.ss_family, SOCK_STREAM, IPPROTO_TCP);	if (fd < 0) {		log_error("unable to create (%s) %d!", strerror(errno),			  ss.ss_family);		return -1;	}	err = connect(fd, (struct sockaddr *) &ss, sizeof(ss));	if (err < 0) {		log_error("unable to connect (%s) %d!", strerror(errno),			  ss.ss_family);		close(fd);		return -1;	}	log_error("%s %d: new connection %d", __FUNCTION__, __LINE__, fd);	if (!strlen(eid)) {		err = isns_get_ip(fd);		if (err) {			close(fd);			return -1;		}	}	isns_fd = fd;	isns_set_fd(fd, scn_listen_fd, scn_fd);	return fd;}static void isns_hdr_init(struct isns_hdr *hdr, uint16_t function,			  uint16_t length, uint16_t flags,			  uint16_t trans, uint16_t sequence){	hdr->version = htons(0x0001);	hdr->function = htons(function);	hdr->length = htons(length);	hdr->flags = htons(flags);	hdr->transaction = htons(trans);	hdr->sequence = htons(sequence);}static int isns_tlv_set(struct isns_tlv **tlv, uint32_t tag, uint32_t length,			void *value){	if (length)		memcpy((*tlv)->value, value, length);	if (length % ISNS_ALIGN)		length += (ISNS_ALIGN - (length % ISNS_ALIGN));	(*tlv)->tag = htonl(tag);	(*tlv)->length = htonl(length);	length += sizeof(struct isns_tlv);	*tlv = (struct isns_tlv *) ((char *) *tlv + length);	return length;}static int isns_scn_deregister(char *name){	int err;	uint16_t flags, length = 0;	char buf[2048];	struct isns_hdr *hdr = (struct isns_hdr *) buf;	struct isns_tlv *tlv;	if (!isns_fd)		if (isns_connect() < 0)			return 0;	memset(buf, 0, sizeof(buf));	tlv = (struct isns_tlv *) hdr->pdu;	length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_NAME, strlen(name), name);	length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_NAME, strlen(name), name);	flags = ISNS_FLAG_CLIENT | ISNS_FLAG_LAST_PDU | ISNS_FLAG_FIRST_PDU;	isns_hdr_init(hdr, ISNS_FUNC_SCN_DEREG, length, flags,		      ++transaction, 0);	err = write(isns_fd, buf, length + sizeof(struct isns_hdr));	if (err < 0)		log_error("%s %d: %s", __FUNCTION__, __LINE__, strerror(errno));	return 0;}#if __BYTE_ORDER == __LITTLE_ENDIAN#define set_scn_flag(x)						\{								\	x = (x & 0x55555555) << 1 | (x & 0xaaaaaaaa) >> 1;	\	x = (x & 0x33333333) << 2 | (x & 0xcccccccc) >> 2;	\	x = (x & 0x0f0f0f0f) << 4 | (x & 0xf0f0f0f0) >> 4;	\	x = (x & 0x00ff00ff) << 8 | (x & 0xff00ff00) >> 8;	\	x = (x & 0x0000ffff) << 16 | (x & 0xffff0000) >> 16;	\}#else#define set_scn_flag(x) (x)#endifstatic int isns_scn_register(void){	int err;	uint16_t flags, length = 0;	uint32_t scn_flags;	char buf[4096];	struct isns_hdr *hdr = (struct isns_hdr *) buf;	struct isns_tlv *tlv;	struct target *target;	if (list_empty(&targets_list))		return 0;	if (!isns_fd)		if (isns_connect() < 0)			return 0;	memset(buf, 0, sizeof(buf));	tlv = (struct isns_tlv *) hdr->pdu;	target = list_entry(targets_list.q_forw, struct target, tlist);	length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_NAME,			       strlen(target->name), target->name);	length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_NAME,			       strlen(target->name), target->name);	length += isns_tlv_set(&tlv, 0, 0, 0);	scn_flags = ISNS_SCN_FLAG_INITIATOR | ISNS_SCN_FLAG_OBJECT_REMOVE |		ISNS_SCN_FLAG_OBJECT_ADDED | ISNS_SCN_FLAG_OBJECT_UPDATED;	set_scn_flag(scn_flags);	scn_flags = htonl(scn_flags);	length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_SCN_BITMAP,			       sizeof(scn_flags), &scn_flags);	flags = ISNS_FLAG_CLIENT | ISNS_FLAG_LAST_PDU | ISNS_FLAG_FIRST_PDU;	isns_hdr_init(hdr, ISNS_FUNC_SCN_REG, length, flags, ++transaction, 0);	err = write(isns_fd, buf, length + sizeof(struct isns_hdr));	if (err < 0)		log_error("%s %d: %s", __FUNCTION__, __LINE__, strerror(errno));	return 0;}static int isns_attr_query(char *name){	int err;	uint16_t flags, length = 0;	char buf[4096];	struct isns_hdr *hdr = (struct isns_hdr *) buf;	struct isns_tlv *tlv;	struct target *target;	uint32_t node = htonl(ISNS_NODE_INITIATOR);	struct isns_qry_mgmt *mgmt;	if (list_empty(&targets_list))		return 0;	if (!isns_fd)		if (isns_connect() < 0)			return 0;	mgmt = malloc(sizeof(*mgmt));	if (!mgmt)		return 0;	insque(&mgmt->qlist, &qry_list);	memset(buf, 0, sizeof(buf));	tlv = (struct isns_tlv *) hdr->pdu;	if (name)		snprintf(mgmt->name, sizeof(mgmt->name), name);	else {		mgmt->name[0] = '\0';		target = list_entry(targets_list.q_forw, struct target, tlist);		name = target->name;	}	length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_NAME, strlen(name), name);	length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_NODE_TYPE,			       sizeof(node), &node);	length += isns_tlv_set(&tlv, 0, 0, 0);	length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_NAME, 0, 0);	length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_NODE_TYPE, 0, 0);	length += isns_tlv_set(&tlv, ISNS_ATTR_PORTAL_IP_ADDRESS, 0, 0);	flags = ISNS_FLAG_CLIENT | ISNS_FLAG_LAST_PDU | ISNS_FLAG_FIRST_PDU;	isns_hdr_init(hdr, ISNS_FUNC_DEV_ATTR_QRY, length, flags,		      ++transaction, 0);	mgmt->transaction = transaction;	err = write(isns_fd, buf, length + sizeof(struct isns_hdr));	if (err < 0)		log_error("%s %d: %s", __FUNCTION__, __LINE__, strerror(errno));	return 0;}static int isns_deregister(void){	int err;	uint16_t flags, length = 0;	char buf[4096];	struct isns_hdr *hdr = (struct isns_hdr *) buf;	struct isns_tlv *tlv;	struct target *target;	if (list_empty(&targets_list))		return 0;	if (!isns_fd)		if (isns_connect() < 0)			return 0;	memset(buf, 0, sizeof(buf));	tlv = (struct isns_tlv *) hdr->pdu;	target = list_entry(targets_list.q_forw, struct target, tlist);	length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_NAME,			       strlen(target->name), target->name);	length += isns_tlv_set(&tlv, 0, 0, 0);	length += isns_tlv_set(&tlv, ISNS_ATTR_ENTITY_IDENTIFIER,			       strlen(eid), eid);	flags = ISNS_FLAG_CLIENT | ISNS_FLAG_LAST_PDU | ISNS_FLAG_FIRST_PDU;	isns_hdr_init(hdr, ISNS_FUNC_DEV_DEREG, length, flags,		      ++transaction, 0);	err = write(isns_fd, buf, length + sizeof(struct isns_hdr));	if (err < 0)		log_error("%s %d: %s", __FUNCTION__, __LINE__, strerror(errno));	return 0;}int isns_target_register(char *name){	char buf[4096];	uint16_t flags = 0, length = 0;	struct isns_hdr *hdr = (struct isns_hdr *) buf;	struct isns_tlv *tlv;	uint32_t port = htonl(ISCSI_LISTEN_PORT);	uint32_t node = htonl(ISNS_NODE_TARGET);	uint32_t type = htonl(2);	struct target *target;	int err, initial = list_length_is_one(&targets_list);	if (!use_isns)		return 0;	if (!isns_fd)		if (isns_connect() < 0)			return 0;	memset(buf, 0, sizeof(buf));	tlv = (struct isns_tlv *) hdr->pdu;        target = list_entry(targets_list.q_back, struct target, tlist);        length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_NAME,			       strlen(target->name), target->name);	length += isns_tlv_set(&tlv, ISNS_ATTR_ENTITY_IDENTIFIER,			       strlen(eid), eid);	length += isns_tlv_set(&tlv, 0, 0, 0);	length += isns_tlv_set(&tlv, ISNS_ATTR_ENTITY_IDENTIFIER,			       strlen(eid), eid);	if (initial) {		length += isns_tlv_set(&tlv, ISNS_ATTR_ENTITY_PROTOCOL,				       sizeof(type), &type);		length += isns_tlv_set(&tlv, ISNS_ATTR_PORTAL_IP_ADDRESS,				       sizeof(ip), &ip);		length += isns_tlv_set(&tlv, ISNS_ATTR_PORTAL_PORT,				       sizeof(port), &port);		flags = ISNS_FLAG_REPLACE;		if (scn_listen_port) {			uint32_t sport = htonl(scn_listen_port);			length += isns_tlv_set(&tlv, ISNS_ATTR_SCN_PORT,					       sizeof(sport), &sport);		}	}	length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_NAME, strlen(name), name);	length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_NODE_TYPE,			       sizeof(node), &node);	flags |= ISNS_FLAG_CLIENT | ISNS_FLAG_LAST_PDU | ISNS_FLAG_FIRST_PDU;	isns_hdr_init(hdr, ISNS_FUNC_DEV_ATTR_REG, length, flags,		      ++transaction, 0);	err = write(isns_fd, buf, length + sizeof(struct isns_hdr));	if (err < 0)		log_error("%s %d: %s", __FUNCTION__, __LINE__, strerror(errno));	if (scn_listen_port)		isns_scn_register();	isns_attr_query(name);	return 0;}static void free_all_acl(struct target *target){	struct isns_initiator *ini;	while (!list_empty(&target->isns_head)) {		ini = list_entry(target->isns_head.q_forw, typeof(*ini), ilist);		remque(&ini->ilist);	}}static struct target *target_lookup_by_name(char *name){	uint32_t tid;	tid = target_find_by_name(name);	if (!tid)		return NULL;	return target_find_by_id(tid);}int isns_target_deregister(char *name){	char buf[4096];	uint16_t flags, length = 0;	struct isns_hdr *hdr = (struct isns_hdr *) buf;	struct isns_tlv *tlv;	int err, last = list_empty(&targets_list);	struct target *target;	target = target_lookup_by_name(name);	if (target)		free_all_acl(target);	if (!use_isns)		return 0;	if (!isns_fd)		if (isns_connect() < 0)			return 0;	isns_scn_deregister(name);	memset(buf, 0, sizeof(buf));	tlv = (struct isns_tlv *) hdr->pdu;	length += isns_tlv_set(&tlv, ISNS_ATTR_ISCSI_NAME, strlen(name), name);	length += isns_tlv_set(&tlv, 0, 0, 0);	if (last)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -