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

📄 ietd.c

📁 iscsi企业级target.很好用
💻 C
字号:
/* * Copyright (C) 2002-2003 Ardis Technolgies <roman@ardistech.com> * * Released under the terms of the GNU GPL v2.0. */#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <getopt.h>#include <netdb.h>#include <sys/poll.h>#include <sys/socket.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/un.h>#include <netinet/in.h>#include <netinet/tcp.h>#include <netinet/ip.h>#include <arpa/inet.h>#include "iscsid.h"#include "ietadm.h"#define LISTEN_MAX		8#define INCOMING_MAX		32enum {	POLL_LISTEN,	POLL_IPC = POLL_LISTEN + LISTEN_MAX,	POLL_NL,	POLL_INCOMING,	POLL_MAX = POLL_INCOMING + INCOMING_MAX,};#define ISCSI_TARGET_DEFAULT_PORT	3260static char* server_address;uint16_t server_port = ISCSI_TARGET_DEFAULT_PORT;static struct pollfd poll_array[POLL_MAX];static struct connection *incoming[INCOMING_MAX];static int incoming_cnt;int ctrl_fd, ipc_fd, nl_fd;static char program_name[] = "iscsid";static struct option const long_options[] ={	{"config", required_argument, 0, 'c'},	{"foreground", no_argument, 0, 'f'},	{"debug", required_argument, 0, 'd'},	{"isns", required_argument, 0, 's'},	{"uid", required_argument, 0, 'u'},	{"gid", required_argument, 0, 'g'},	{"address", required_argument, 0, 'a'},	{"port", required_argument, 0, 'p'},	{"version", no_argument, 0, 'v'},	{"help", no_argument, 0, 'h'},	{0, 0, 0, 0},};/* This will be comfigurable by command line options */extern struct config_operations plain_ops;struct config_operations *cops = &plain_ops;static void usage(int status){	if (status != 0)		fprintf(stderr, "Try `%s --help' for more information.\n", program_name);	else {		printf("Usage: %s [OPTION]\n", program_name);		printf("\iSCSI target daemon.\n\  -c, --config=[path]     Execute in the config file.\n");		printf("\  -f, --foreground        make the program run in the foreground\n\  -d, --debug debuglevel  print debugging information\n\  -s, --isns=[ip]         work with isns server, default is disabled\n\  -u, --uid=uid           run as uid, default is current user\n\  -g, --gid=gid           run as gid, default is current user group\n\  -a, --address=address   listen on specified local address instead of all\n\  -p, --port=port         listen on specified port instead of 3260\n\  -h, --help              display this help and exit\n\");	}	exit(1);}static void set_non_blocking(int fd){	int res = fcntl(fd, F_GETFL);	if (res != -1) {		res = fcntl(fd, F_SETFL, res | O_NONBLOCK);		if (res)			log_warning("unable to set fd flags (%s)!", strerror(errno));	} else		log_warning("unable to get fd flags (%s)!", strerror(errno));}static void create_listen_socket(struct pollfd *array){	struct addrinfo hints, *res, *res0;	char servname[64];	int i, sock, opt;	memset(servname, 0, sizeof(servname));	snprintf(servname, sizeof(servname), "%d", server_port);	memset(&hints, 0, sizeof(hints));	hints.ai_socktype = SOCK_STREAM;	hints.ai_flags = AI_PASSIVE;	if (getaddrinfo(server_address, servname, &hints, &res0)) {		log_error("unable to get address info (%s)!", strerror(errno));		exit(1);	}	for (i = 0, res = res0; res && i < LISTEN_MAX; i++, res = res->ai_next) {		sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);		if (sock < 0) {			log_error("unable to create server socket (%s) %d %d %d!",				  strerror(errno), res->ai_family,				  res->ai_socktype, res->ai_protocol);			continue;		}		opt = 1;		if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)))			log_warning("unable to set SO_REUSEADDR on server socket (%s)!",				    strerror(errno));		opt = 1;		if (res->ai_family == AF_INET6 &&		    setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)))			continue;		if (bind(sock, res->ai_addr, res->ai_addrlen)) {			log_error("unable to bind server socket (%s)!", strerror(errno));			continue;		}		if (listen(sock, INCOMING_MAX)) {			log_error("unable to listen to server socket (%s)!", strerror(errno));			continue;		}		set_non_blocking(sock);		array[i].fd = sock;		array[i].events = POLLIN;	}	freeaddrinfo(res0);}static void accept_connection(int listen){	struct sockaddr_storage from;	socklen_t namesize;	struct pollfd *pollfd;	struct connection *conn;	int fd, i;	namesize = sizeof(from);	if ((fd = accept(listen, (struct sockaddr *) &from, &namesize)) < 0) {		if (errno != EINTR && errno != EAGAIN) {			perror("accept(incoming_socket)");			exit(1);		}		return;	}	for (i = 0; i < INCOMING_MAX; i++) {		if (!incoming[i])			break;	}	if (i >= INCOMING_MAX) {		log_error("unable to find incoming slot? %d\n", i);		exit(1);	}	if (!(conn = conn_alloc())) {		log_error("fail to allocate %s", "conn\n");		exit(1);	}	conn->fd = fd;	incoming[i] = conn;	conn_read_pdu(conn);	set_non_blocking(fd);	pollfd = &poll_array[POLL_INCOMING + i];	pollfd->fd = fd;	pollfd->events = POLLIN;	pollfd->revents = 0;	incoming_cnt++;	if (incoming_cnt >= INCOMING_MAX)		poll_array[POLL_LISTEN].events = 0;}void event_loop(void){	int res, i, opt;	struct connection *conn;	struct pollfd *pollfd;	create_listen_socket(poll_array + POLL_LISTEN);	poll_array[POLL_IPC].fd = ipc_fd;	poll_array[POLL_IPC].events = POLLIN;	poll_array[POLL_NL].fd = nl_fd;	poll_array[POLL_NL].events = POLLIN;	for (i = 0; i < INCOMING_MAX; i++) {		poll_array[POLL_INCOMING + i].fd = -1;		poll_array[POLL_INCOMING + i].events = 0;		incoming[i] = NULL;	}	while (1) {		res = poll(poll_array, POLL_MAX, -1);		if (res <= 0) {			if (res < 0 && errno != EINTR) {				perror("poll()");				exit(1);			}			continue;		}		for (i = 0; i < LISTEN_MAX; i++) {			if (poll_array[POLL_LISTEN + i].revents			    && incoming_cnt < INCOMING_MAX)				accept_connection(poll_array[POLL_LISTEN + i].fd);		}		if (poll_array[POLL_NL].revents)			handle_iscsi_events(nl_fd);		if (poll_array[POLL_IPC].revents)			ietadm_request_handle(ipc_fd);		for (i = 0; i < INCOMING_MAX; i++) {			conn = incoming[i];			pollfd = &poll_array[POLL_INCOMING + i];			if (!conn || !pollfd->revents)				continue;			pollfd->revents = 0;			switch (conn->iostate) {			case IOSTATE_READ_BHS:			case IOSTATE_READ_AHS_DATA:			read_again:				res = read(pollfd->fd, conn->buffer, conn->rwsize);				if (res <= 0) {					if (res == 0 || (errno != EINTR && errno != EAGAIN))						conn->state = STATE_CLOSE;					else if (errno == EINTR)						goto read_again;					break;				}				conn->rwsize -= res;				conn->buffer += res;				if (conn->rwsize)					break;				switch (conn->iostate) {				case IOSTATE_READ_BHS:					conn->iostate = IOSTATE_READ_AHS_DATA;					conn->req.ahssize = conn->req.bhs.ahslength * 4;					conn->req.datasize = ((conn->req.bhs.datalength[0] << 16) +							      (conn->req.bhs.datalength[1] << 8) +							      conn->req.bhs.datalength[2]);					conn->rwsize = (conn->req.ahssize + conn->req.datasize + 3) & -4;					if (conn->rwsize) {						if (!conn->req_buffer)							conn->req_buffer = malloc(INCOMING_BUFSIZE);						conn->buffer = conn->req_buffer;						conn->req.ahs = conn->buffer;						conn->req.data = conn->buffer + conn->req.ahssize;						goto read_again;					}				case IOSTATE_READ_AHS_DATA:					conn_write_pdu(conn);					pollfd->events = POLLOUT;					log_pdu(2, &conn->req);					if (!cmnd_execute(conn))						conn->state = STATE_CLOSE;					break;				}				break;			case IOSTATE_WRITE_BHS:			case IOSTATE_WRITE_AHS:			case IOSTATE_WRITE_DATA:			write_again:				opt = 1;				setsockopt(pollfd->fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt));				res = write(pollfd->fd, conn->buffer, conn->rwsize);				if (res < 0) {					if (errno != EINTR && errno != EAGAIN)						conn->state = STATE_CLOSE;					else if (errno == EINTR)						goto write_again;					break;				}				conn->rwsize -= res;				conn->buffer += res;				if (conn->rwsize)					goto write_again;				switch (conn->iostate) {				case IOSTATE_WRITE_BHS:					if (conn->rsp.ahssize) {						conn->iostate = IOSTATE_WRITE_AHS;						conn->buffer = conn->rsp.ahs;						conn->rwsize = conn->rsp.ahssize;						goto write_again;					}				case IOSTATE_WRITE_AHS:					if (conn->rsp.datasize) {						int o;						conn->iostate = IOSTATE_WRITE_DATA;						conn->buffer = conn->rsp.data;						conn->rwsize = conn->rsp.datasize;						o = conn->rwsize & 3;						if (o) {							for (o = 4 - o; o; o--)								*((u8 *)conn->buffer + conn->rwsize++) = 0;						}						goto write_again;					}				case IOSTATE_WRITE_DATA:					opt = 0;					setsockopt(pollfd->fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt));					cmnd_finish(conn);					switch (conn->state) {					case STATE_KERNEL:						conn_take_fd(conn, pollfd->fd);						conn->state = STATE_CLOSE;						break;					case STATE_EXIT:					case STATE_CLOSE:						break;					default:						conn_read_pdu(conn);						pollfd->events = POLLIN;						break;					}					break;				}				break;			default:				log_error("illegal iostate %d for port %d!\n", conn->iostate, i);				exit(1);			}			if (conn->state == STATE_CLOSE) {				log_debug(0, "connection closed");				conn_free_pdu(conn);				conn_free(conn);				close(pollfd->fd);				pollfd->fd = -1;				incoming[i] = NULL;				incoming_cnt--;			}		}	}}int main(int argc, char **argv){	int ch, longindex;	char *config = NULL;	char isns_ip[32];	uid_t uid = 0;	gid_t gid = 0;	while ((ch = getopt_long(argc, argv, "c:fd:s:u:g:a:p:vh", long_options, &longindex)) >= 0) {		switch (ch) {		case 'c':			config = optarg;			break;		case 'f':			log_daemon = 0;			break;		case 'd':			log_level = atoi(optarg);			break;		case 's':			memset(isns_ip, 0, sizeof(isns_ip));			strncpy(isns_ip, optarg, sizeof(isns_ip));			use_isns = 1;			break;		case 'u':			uid = strtoul(optarg, NULL, 10);			break;		case 'g':			gid = strtoul(optarg, NULL, 10);			break;		case 'a':			server_address = strdup(optarg);			break;		case 'p':			server_port = (uint16_t)strtoul(optarg, NULL, 10);			break;		case 'v':			printf("%s version %s\n", program_name, IET_VERSION_STRING);			exit(0);			break;		case 'h':			usage(0);			break;		default:			usage(1);			break;		}	}	if ((nl_fd = nl_open()) < 0) {		perror("netlink fd\n");		exit(-1);	};	if ((ctrl_fd = ki->ctldev_open()) < 0) {		perror("ctldev fd\n");		exit(-1);	}	if ((ipc_fd = ietadm_request_listen()) < 0) {		perror("ipc fd\n");		exit(-1);	}	log_init();	if (log_daemon) {		char buf[64];		pid_t pid;		int fd;		fd = open("/var/run/iscsi_trgt.pid", O_WRONLY|O_CREAT, 0644);		if (fd < 0) {			log_error("unable to create pid file");			exit(1);		}		pid = fork();		if (pid < 0) {			log_error("starting daemon failed");			exit(1);		} else if (pid)			exit(0);		chdir("/");		if (lockf(fd, F_TLOCK, 0) < 0) {			log_error("unable to lock pid file");			exit(1);		}		ftruncate(fd, 0);		sprintf(buf, "%d\n", getpid());		write(fd, buf, strlen(buf));		close(0);		open("/dev/null", O_RDWR);		dup2(0, 1);		dup2(0, 2);		setsid();	}	if (use_isns) {		if (initialize_iet_isns(isns_ip, server_port) < 0)			use_isns = 0;	}	cops->init(config);	if (gid && setgid(gid) < 0)		perror("setgid\n");	if (uid && setuid(uid) < 0)		perror("setuid\n");	event_loop();	if (use_isns) {		cleanup_iet_isns();	}	return 0;}

⌨️ 快捷键说明

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