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

📄 isns.c

📁 Ubuntu公司提供免费的iSCSI Target
💻 C
📖 第 1 页 / 共 2 页
字号:
		length += isns_tlv_set(&tlv, ISNS_ATTR_ENTITY_IDENTIFIER,				       strlen(eid), eid);	else		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_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;}static int recv_hdr(int fd, struct isns_io *rx, struct isns_hdr *hdr){	int err;	if (rx->offset < sizeof(*hdr)) {		err = read(fd, rx->buf + rx->offset,			   sizeof(*hdr) - rx->offset);		if (err < 0) {			if (errno == EAGAIN || errno == EINTR)				return -EAGAIN;			log_error("header read error %d %d %d %d",				  fd, err, errno, rx->offset);			return -1;		} else if (err == 0)			return -1;		log_debug(1, "header %d %d bytes!", fd, err);		rx->offset += err;		if (rx->offset < sizeof(*hdr)) {			log_debug(1, "header wait %d %d", rx->offset, err);			return -EAGAIN;		}	}	return 0;}#define get_hdr_param(hdr, function, length, flags, transaction, sequence)	\{										\	function = ntohs(hdr->function);					\	length = ntohs(hdr->length);						\	flags = ntohs(hdr->flags);						\	transaction = ntohs(hdr->transaction);					\	sequence = ntohs(hdr->sequence);					\}static int recv_pdu(int fd, struct isns_io *rx, struct isns_hdr *hdr){	uint16_t function, length, flags, transaction, sequence;	int err;	err = recv_hdr(fd, rx, hdr);	if (err)		return err;	/* Now we got a complete header */	get_hdr_param(hdr, function, length, flags, transaction, sequence);	log_debug(1, "got a header %x %u %x %u %u", function, length, flags,		  transaction, sequence);	if (length + sizeof(*hdr) > BUFSIZE) {		log_error("FIXME we cannot handle this yet %u!", length);		return -1;	}	if (rx->offset < length + sizeof(*hdr)) {		err = read(fd, rx->buf + rx->offset,			   length + sizeof(*hdr) - rx->offset);		if (err < 0) {			if (errno == EAGAIN || errno == EINTR)				return -EAGAIN;			log_error("pdu read error %d %d %d %d",				  fd, err, errno, rx->offset);			return -1;		} else if (err == 0)			return -1;		log_debug(1, "pdu %u %u", fd, err);		rx->offset += err;		if (rx->offset < length + sizeof(*hdr)) {			log_error("pdu wait %d %d", rx->offset, err);			return -EAGAIN;		}	}	/* Now we got everything. */	rx->offset = 0;	return 0;}#define print_unknown_pdu(hdr)						\{									\	uint16_t function, length, flags, transaction, sequence;	\	get_hdr_param(hdr, function, length, flags, transaction,	\		      sequence)						\	log_error("%s %d: unknown function %x %u %x %u %u",		\		  __FUNCTION__, __LINE__,				\		  function, length, flags, transaction, sequence);	\}static char *print_scn_pdu(struct isns_hdr *hdr){	struct isns_tlv *tlv = (struct isns_tlv *) hdr->pdu;	uint16_t function, length, flags, transaction, sequence;	char *name = NULL;	get_hdr_param(hdr, function, length, flags, transaction, sequence);	while (length) {		uint32_t vlen = ntohl(tlv->length);		switch (ntohl(tlv->tag)) {		case ISNS_ATTR_ISCSI_NAME:			log_error("scn name: %u, %s", vlen, (char *) tlv->value);			if (!name)				name = (char *) tlv->value;			break;		case ISNS_ATTR_TIMESTAMP:/* 			log_error("%u : %u : %" PRIx64, ntohl(tlv->tag), vlen, *//* 				  *((uint64_t *) tlv->value)); */			break;		case ISNS_ATTR_ISCSI_SCN_BITMAP:			log_error("scn bitmap : %x", *((uint32_t *) tlv->value));			break;		}		length -= (sizeof(*tlv) + vlen);		tlv = (struct isns_tlv *) ((char *) tlv->value + vlen);	}	return name;}static void qry_rsp_handle(struct isns_hdr *hdr){	struct isns_tlv *tlv;	uint16_t function, length, flags, transaction, sequence;	uint32_t status = (uint32_t) (*hdr->pdu);	struct isns_qry_mgmt *mgmt, *n;	struct target *target;	struct isns_initiator *ini;	char *name = NULL;	get_hdr_param(hdr, function, length, flags, transaction, sequence);	list_for_each_entry_safe(mgmt, n, &qry_list, qlist) {		if (mgmt->transaction == transaction) {			remque(&mgmt->qlist);			goto found;		}	}	log_error("%s %d: transaction not found %u",		  __FUNCTION__, __LINE__, transaction);	return;found:	if (status) {		log_error("%s %d: error response %u",			  __FUNCTION__, __LINE__, status);		goto free_qry_mgmt;	}	if (!strlen(mgmt->name)) {		log_debug(1, "%s %d: skip %u",			  __FUNCTION__, __LINE__, transaction);		goto free_qry_mgmt;	}	target = target_lookup_by_name(mgmt->name);	if (!target) {		log_error("%s %d: invalid tid %s",			  __FUNCTION__, __LINE__, mgmt->name);		goto free_qry_mgmt;	}	free_all_acl(target);	/* skip status */	tlv = (struct isns_tlv *) ((char *) hdr->pdu + 4);	length -= 4;	while (length) {		uint32_t vlen = ntohl(tlv->length);		switch (ntohl(tlv->tag)) {		case ISNS_ATTR_ISCSI_NAME:			name = (char *) tlv->value;			break;		case ISNS_ATTR_ISCSI_NODE_TYPE:			if (ntohl(*(tlv->value)) == ISNS_NODE_INITIATOR && name) {				log_error("%s %d: %s", __FUNCTION__, __LINE__,					  (char *) name);				ini = malloc(sizeof(*ini));				if (!ini)					goto free_qry_mgmt;				snprintf(ini->name, sizeof(ini->name), name);				insque(&ini->ilist, &target->isns_head);			} else				name = NULL;			break;		default:			name = NULL;			break;		}		length -= (sizeof(*tlv) + vlen);		tlv = (struct isns_tlv *) ((char *) tlv->value + vlen);	}free_qry_mgmt:	free(mgmt);}int isns_handle(int is_timeout, int *timeout){	int err;	struct isns_io *rx = &isns_rx;	struct isns_hdr *hdr = (struct isns_hdr *) rx->buf;	uint32_t result;	uint16_t function, length, flags, transaction, sequence;	char *name = NULL;	if (is_timeout)		return isns_attr_query(NULL);	err = recv_pdu(isns_fd, rx, hdr);	if (err) {		if (err == -EAGAIN)			return err;		log_debug(1, "%s %d: close connection %d", __FUNCTION__, __LINE__,			  isns_fd);		close(isns_fd);		isns_fd = 0;		isns_set_fd(0, scn_listen_fd, scn_fd);		return err;	}	get_hdr_param(hdr, function, length, flags, transaction, sequence);	result = ntohl((uint32_t) hdr->pdu[0]);	switch (function) {	case ISNS_FUNC_DEV_ATTR_REG_RSP:		break;	case ISNS_FUNC_DEV_ATTR_QRY_RSP:		qry_rsp_handle(hdr);		break;	case ISNS_FUNC_DEV_DEREG_RSP:	case ISNS_FUNC_SCN_REG_RSP:		break;	case ISNS_FUNC_SCN:		name = print_scn_pdu(hdr);		if (name) {			log_error("%s %d: %s", __FUNCTION__, __LINE__, name);			isns_attr_query(name);		}		break;	default:		print_unknown_pdu(hdr);	}	return 0;}static int scn_accept_connection(void){	struct sockaddr_storage from;	socklen_t slen;	int fd, err, opt = 1;	slen = sizeof(from);	fd = accept(scn_listen_fd, (struct sockaddr *) &from, &slen);	if (fd < 0) {		log_error("%s %d: accept error %s", __FUNCTION__, __LINE__,			  strerror(errno));		return -errno;	}	log_error("Accept scn connection %d", fd);	err = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));	if (err)		log_error("%s %d: %s\n", __FUNCTION__, __LINE__,			  strerror(errno));	/* not critical, so ignore. */	scn_fd = fd;	isns_set_fd(isns_fd, scn_listen_fd, scn_fd);	return 0;}static void send_scn_rsp(char *name, uint16_t transaction){	char buf[1024];	struct isns_hdr *hdr = (struct isns_hdr *) buf;	struct isns_tlv *tlv;	uint16_t flags, length = 0;	int err;	memset(buf, 0, sizeof(buf));	*((uint32_t *) hdr->pdu) = 0;	tlv = (struct isns_tlv *) ((char *) hdr->pdu + 4);	length +=4;	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_RSP, length, flags, transaction, 0);	err = write(scn_fd, buf, length + sizeof(struct isns_hdr));	if (err < 0)		log_error("%s %d: %s", __FUNCTION__, __LINE__, strerror(errno));}int isns_scn_handle(int is_accept){	int err;	struct isns_io *rx = &scn_rx;	struct isns_hdr *hdr = (struct isns_hdr *) rx->buf;	uint16_t function, length, flags, transaction, sequence;	char *name = NULL;	log_error("%s %d: %d", __FUNCTION__, __LINE__, is_accept);	if (is_accept)		return scn_accept_connection();	err = recv_pdu(scn_fd, rx, hdr);	if (err) {		if (err == -EAGAIN)			return err;		log_debug(1, "%s %d: close connection %d", __FUNCTION__, __LINE__,			  scn_fd);		close(scn_fd);		scn_fd = 0;		isns_set_fd(isns_fd, scn_listen_fd, 0);		return err;	}	get_hdr_param(hdr, function, length, flags, transaction, sequence);	switch (function) {	case ISNS_FUNC_SCN:		name = print_scn_pdu(hdr);		break;	default:		print_unknown_pdu(hdr);	}	if (name) {		send_scn_rsp(name, transaction);		isns_attr_query(name);	}	return 0;}static int scn_init(char *addr){	int fd, opt, err;	struct sockaddr_storage lss;	socklen_t slen;	fd = socket(ss.ss_family, SOCK_STREAM, IPPROTO_TCP);	if (fd < 0) {		log_error("%s %d: %s\n", __FUNCTION__, __LINE__, strerror(errno));		return -errno;	}	opt = 1;	if (ss.ss_family == AF_INET6) {		err = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));		if (err)			log_error("%s %d: %s\n", __FUNCTION__, __LINE__,				  strerror(errno));		goto out;	}	err = listen(fd, 5);	if (err) {		log_error("%s %d: %s\n", __FUNCTION__, __LINE__, strerror(errno));		goto out;	}	slen = sizeof(lss);	err = getsockname(fd, (struct sockaddr *) &lss, &slen);	if (err) {		log_error("%s %d: %s\n", __FUNCTION__, __LINE__, strerror(errno));		goto out;	}	/* protocol independent way ? */	if (lss.ss_family == AF_INET6)		scn_listen_port = ntohs(((struct sockaddr_in6 *) &lss)->sin6_port);	else		scn_listen_port = ntohs(((struct sockaddr_in *) &lss)->sin_port);	log_error("scn listen port %u %d %d\n", scn_listen_port, fd, err);out:	if (err)		close(fd);	else {		scn_listen_fd = fd;		isns_set_fd(isns_fd, scn_listen_fd, scn_fd);	}	return err;}int isns_init(char *addr, int isns_ac){	int err;	char port[8];	struct addrinfo hints, *res;	snprintf(port, sizeof(port), "%d", ISNS_PORT);	memset(&hints, 0, sizeof(hints));	hints.ai_socktype = SOCK_STREAM;	err = getaddrinfo(addr, (char *) &port, &hints, &res);	if (err) {		log_error("getaddrinfo error %s, %s", gai_strerror(err), addr);		return -1;	}	memcpy(&ss, res->ai_addr, sizeof(ss));	freeaddrinfo(res);	rxbuf = calloc(2, BUFSIZE);	if (!rxbuf) {		log_error("oom!");		return -1;	}	scn_init(addr);	isns_rx.buf = rxbuf;	isns_rx.offset = 0;	scn_rx.buf = rxbuf + BUFSIZE;	scn_rx.offset = 0;	use_isns = 1;	use_isns_ac = isns_ac;	return current_timeout * 1000;}void isns_exit(void){	struct target *target;	if (!use_isns)		return;	list_for_each_entry(target, &targets_list, tlist)		isns_scn_deregister(target->name);	isns_deregister();	/* we can't receive events any more. */	isns_set_fd(0, 0, 0);	if (isns_fd)		close(isns_fd);	if (scn_listen_fd)		close(scn_listen_fd);	if (scn_fd)		close(scn_fd);	free(rxbuf);}

⌨️ 快捷键说明

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