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

📄 iscsi-network-boot.c

📁 ISCSI user client software.Client would be used to access the IPSAN server.
💻 C
字号:
/* * iSCSI driver for Linux * Copyright (C) 2002 Cisco Systems, Inc. * maintained by linux-iscsi-devel@lists.sourceforge.net * * 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. * * See the file COPYING included with this distribution for more details. * * $Id: iscsi-network-boot.c,v 1.17 2005/02/14 09:14:02 smithan Exp $ * */#include <fcntl.h>#include <errno.h>#include <unistd.h>#include <sys/stat.h>#include <net/route.h>#include "iscsi-sfnet.h"#include "iscsi-ioctl.h"#include "iscsid.h"#include "iscsi-login.h"#include "iscsi-network-boot.h"#define ISCSI_DEVICE "/dev/iscsictl"#define NETDEV_BOOT_SETUP_MAX 8static int control_fd = -1;static char inbp_interface_name[IFNAMSIZ];static intopen_control_device(void){	FILE *f = NULL;	char devname[256], buf[256];	int devn, ctlfd;	/*	 * Establish the control path to the driver	 */	f = fopen("/proc/devices", "r");	if (!f) {		perror("Cannot open control path to the driver");		return -1;	}	devn = 0;	while (!feof(f)) {		if (!fgets(buf, sizeof (buf), f)) {			break;		}		if (sscanf(buf, "%d %s", &devn, devname) != 2) {			continue;		}		if (!strcmp(devname, "iscsictl")) {			break;		}		devn = 0;	}	fclose(f);	if (!devn) {		printf		    ("cannot find iscsictl in /proc/devices - make "		     "sure the module is loaded");		return -1;	}	unlink(ISCSI_DEVICE);	if (mknod(ISCSI_DEVICE, (S_IFCHR | 0600), (devn << 8))) {		printf("cannot create %s ", ISCSI_DEVICE);		return -1;	}	ctlfd = open(ISCSI_DEVICE, O_RDWR);	if (ctlfd < 0) {		printf("cannot open %s", ISCSI_DEVICE);		return -1;	}	return ctlfd;}static char *get_initiatorname(char *pathname){	FILE *f = NULL;	int c;	char *line, buffer[1024], *name = NULL;	if (!pathname) {		printf("No pathname to load InitiatorName from");		return NULL;	}	/* get the InitiatorName */	if ((f = fopen(pathname, "r"))) {		while ((line = fgets(buffer, sizeof (buffer), f))) {			while (line && isspace(c = *line))				line++;			if (strncmp(line, "InitiatorName=", 14) == 0) {				char *end = line + 14;				/* the name is everything up to the first bit				 * of whitespace				 */				while (*end && (!isspace(c = *end)))					end++;				if (isspace(c = *end))					*end = '\0';				if (end > line + 14)					name = strdup(line + 14);			}		}		fclose(f);		if (!name) {			printf			    ("an InitiatorName is required, but was not "			     "found in %s",			     pathname);			return NULL;		} else {			printf("InitiatorName=%s\n", name);		}		return name;	} else {		printf("cannot open InitiatorName configuration file %s",		       pathname);		return NULL;	}}/* * Assumptions for network boot: * 1. Only one portal available which comes from nbp structure  * 2. No authentication is used. * 3. Digest values are not configurable on initiator side, user can set it on *    target if required. * 4. Tag is always 1, as there is no value in nbp specifying portal tag. * 5. Initiator name for boot and normal sessions will be different(FIXME). *//* Returns 0 on success, non zero on failure */static intioctl_establish_session(struct sapiNBP *nbp){	int rc, ret = 0;	struct iscsi_session_ioctl *ioctld = NULL;	struct sockaddr_in *addr;	/* allocate an ioctl structure with enough space	 * for all of the portal info	 */	ioctld =	    calloc(1, sizeof (*ioctld) + sizeof (struct iscsi_portal_info));	if (ioctld == NULL) {		printf("failed to allocate %d bytes for ioctl data structure",		       sizeof (*ioctld) + sizeof (struct iscsi_portal_info));		return 1;	}	ioctld->ioctl_version = ISCSI_SESSION_IOCTL_VERSION;	ioctld->config_number = 1;	ioctld->update = 0;	ioctld->portal.login_timeout = 15;	ioctld->portal.auth_timeout = 45;	ioctld->portal.active_timeout = 5;	ioctld->portal.idle_timeout = 60;	ioctld->portal.ping_timeout = 5;	ioctld->portal.replacement_timeout = 0;	ioctld->portal.abort_timeout = 10;	ioctld->portal.reset_timeout = 30;	ioctld->portal.initial_r2t = 0;	ioctld->portal.immediate_data = 0;	ioctld->portal.max_recv_data_segment_len = 128 * 1024;	ioctld->portal.first_burst_len = 256 * 1024;	ioctld->portal.max_burst_len = (16 * 1024 * 1024) - 1024;	ioctld->portal.def_time2wait = 0;	ioctld->portal.def_time2retain = 0;	ioctld->portal.data_digest = ISCSI_DIGEST_NONE_CRC32C;	ioctld->portal.header_digest = ISCSI_DIGEST_NONE_CRC32C;	ioctld->portal.tcp_window_size = 256 * 1024;	addr = (struct sockaddr_in *)&ioctld->portal.addr;	addr->sin_family = AF_INET;	memcpy(&addr->sin_addr.s_addr, (char *)(&nbp->targetipaddr),	       sizeof(nbp->targetipaddr));	addr->sin_port = htons(nbp->tcpport);	ioctld->portal.tag = PORTAL_GROUP_TAG_UNKNOWN;	ioctld->password_length = 0;	ioctld->password_length_in = 0;	printf("authentication not configured for target");	strcpy(ioctld->initiator_name,	       get_initiatorname("/etc/initiatorname.iscsi"));	strcpy(ioctld->target_name, nbp->targetstring);	ioctld->isid[0] = DRIVER_ISID_0;	ioctld->isid[1] = DRIVER_ISID_1;	ioctld->isid[2] = DRIVER_ISID_2;	ioctld->isid[3] = 0;	ioctld->isid[4] = 0;	ioctld->isid[5] = 1;	/*	 * Tell the kernel to establish a session.	 */	do {		rc = ioctl(control_fd, ISCSI_ESTABLISH_SESSION,			   (char *) ioctld);		if (rc < 0) {			printf("iSCSI session ioctl failed for %s, errno = %d",			       nbp->targetstring, errno);			printf			    ("\nRetrying session establishment with "			     "the boot disk ...\n");			sleep(2);		} else {			printf			    ("iSCSI session ioctl for %s returned from "			     "kernel with rc %d",			     nbp->targetstring, rc);		}	       	} while (rc < 0);	memset(&ioctld, 0, sizeof (ioctld));	return ret;}static intfind_pxe_sig(char *buf, int iter, struct sapiNBP *nbp){	int len, i = 0;	char *p = buf, *sig = SIGNATURE;	len = strlen(sig);	while (INBP_BUF_SIZE - i >= len) {		if (strncmp(p, sig, len) == 0) {			printf("\nGot the signature at 0x%x\n",			       iter * INBP_BUF_SIZE + i);			memcpy(nbp, p, sizeof (struct sapiNBP));			printf("targetname: %s\n\n", nbp->targetstring);			return 1;		}		p++;		i++;	}	return 0;}voidget_inbp_info(struct sapiNBP *nbp){	int fd, i = 0;	char buf[1024];	if ((fd = open("/dev/mem", O_RDONLY)) < 0) {		perror("open mem");		return;	}	while (i < SCANAREA) {		if (read(fd, buf, INBP_BUF_SIZE) < 0) {			printf("Read error at 0x%x\n", i * INBP_BUF_SIZE);			perror("read");			return;		}		i++;		/* printf("Reading %dk area..\n", i); */		if (find_pxe_sig(buf, i, nbp))			break;	}	if (i > SCANAREA) {		printf("\n%s not found, iscsi boot will fail !!!\n", SIGNATURE);		sleep(10);	}}/* Returns 0 on success, non zero on error */static intiscsi_add_route(struct sapiNBP *nbp){	struct rtentry rt;	struct sockaddr_in *dst = (struct sockaddr_in *) &rt.rt_dst;	struct sockaddr_in *gw = (struct sockaddr_in *) &rt.rt_gateway;	char dev[IFNAMSIZ], ip[16];	int ret, fd;	memset((char *) &rt, 0, sizeof (struct rtentry));	memset(ip, 0, 16);	memset(dev, 0, IFNAMSIZ);	dst->sin_family = AF_INET;	dst->sin_addr.s_addr = INADDR_ANY;	strcpy(ip, (char *) (&nbp->ripaddr));	strcpy(dev, inbp_interface_name);	gw->sin_family = AF_INET;	memcpy(&gw->sin_addr.s_addr, ip, 4);	rt.rt_flags = (RTF_UP | RTF_GATEWAY);	rt.rt_dev = dev;	fd = socket(AF_INET,SOCK_STREAM,0);	if (fd == -1) {		printf("\nFailed to create socket with errno %d\n", errno);		return 1;	}	ret = ioctl(fd, SIOCADDRT, &rt);	if(ret != 0)		printf("iSCSI: error in setting the route, ioctl returned "		       "with value: %d\n", ret);	return ret;}/* Returns 1 on success 0 on failure */static intiscsi_set_if_addr(struct sapiNBP *nbp){	struct ifreq ifr;	struct sockaddr sa;	struct sockaddr_in *sin = (struct sockaddr_in *) &sa;	int dev_ret = 0, fd;	memset(&ifr, 0, sizeof (struct ifreq));	memset(&sa, 0, sizeof (struct sockaddr));	if (nbp->myipaddr != 0) {		memcpy(&sin->sin_addr,		       (char *)&nbp->myipaddr, 4);	} else {		printf("\nERROR !!! Not setting ip from inbp !!!\n");		return 0;	}	if (inbp_interface_name != NULL) {		strcpy(ifr.ifr_name, inbp_interface_name);	} else {		printf("\nERROR !!! Not setting interface from inbp !!!\n");		return 0;	}	fd = socket(AF_INET,SOCK_STREAM,0);	if (fd == -1) {		printf("\nFailed to create socket with errno %d\n", errno);		return 0;	}	/* Check if the interface is already up or not */	if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) {		if ((ifr.ifr_flags & IFF_UP) != 0) {			printf			    ("\nInterface %s has IFF_UP flag already set\n",			     ifr.ifr_name);			return 1;		}	} else {		printf		    ("\niSCSI: ERROR in getting interface FLAGS for "		     "interface %s\n",		     ifr.ifr_name);		return 0;	}	memset(&ifr, 0, sizeof (struct ifreq));	strcpy(ifr.ifr_name, inbp_interface_name);	sin->sin_family = AF_INET;	sin->sin_port = 0;	memcpy(&ifr.ifr_addr, &sa, sizeof (struct sockaddr));	if ((dev_ret = ioctl(fd, SIOCSIFADDR, (void *) &ifr)) != 0) {		printf		    ("\niSCSI: ERROR in setting ip address for interface %s\n",		     ifr.ifr_name);		return 0;	}	memset(&ifr, 0, sizeof (struct ifreq));	if (inbp_interface_name != NULL) {		strcpy(ifr.ifr_name, inbp_interface_name);	} else {		printf("\nERROR !!! Not setting interface from inbp !!!\n");		return 0;	}	ifr.ifr_flags |= IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_MULTICAST;	if ((dev_ret = ioctl(fd, SIOCSIFFLAGS, (void *) &ifr)) != 0) {		printf("\niSCSI: ERROR in setting flags for interface %s\n",		       ifr.ifr_name);		return 0;	}	memset(&ifr, 0, sizeof (struct ifreq));	strcpy(ifr.ifr_name, inbp_interface_name);	memcpy(&sin->sin_addr, &nbp->myipmask,	       4);	memcpy(&ifr.ifr_netmask, &sa,	       sizeof (struct sockaddr));	if ((dev_ret = ioctl(fd, SIOCSIFNETMASK, (void *) &ifr)) != 0) {		printf		    ("\niSCSI: ERROR in setting network mask "		     "for interface %s\n",		     ifr.ifr_name);		return 0;	}	while (iscsi_add_route(nbp)) {		printf("\niSCSI: iscsi_set_if_addr: iscsi_add_route failed\n");		sleep(2);	}	return 1;}/* Return 1 on sucess, 0 on error.*/intbring_up_network(struct sapiNBP *nbp){	int fd, tmp_index;	struct ifreq req;	fd = socket(AF_INET,SOCK_STREAM,0);	if (fd == -1) {		printf("/n failed to create socket with errno %d\n", errno);		return 0;    	}    	for (tmp_index = 1; tmp_index < NETDEV_BOOT_SETUP_MAX; tmp_index++) {		memset(&req,0,sizeof(req));		req.ifr_ifindex = tmp_index;		if (ioctl(fd, SIOCGIFNAME, &req) < 0) {			printf("iSCSI: error in getting interface name\n");			return 0;		}		req.ifr_ifindex = 0;		if (ioctl(fd, SIOCGIFHWADDR, &req) < 0) {			printf("iSCSI: error in getting hardware address\n");			return 0;		}		if (!memcmp(nbp->myethaddr, req.ifr_hwaddr.sa_data,			    IFHWADDRLEN)){			strcpy(inbp_interface_name, req.ifr_name);			break;		}	}	while(!iscsi_set_if_addr(nbp)) {		printf("\niSCSI: iscsi_set_if_addr failed\n");	}	return 1;}voidestablish_iscsi_network_boot_session(struct sapiNBP *nbp){	int rv = 0;	/* ensure the control device exists, and open it for all of	 * the child processes to use	 */	for (;;) {		control_fd = open_control_device();		if (control_fd >= 0)			break;		printf		    ("could not open control device %s. Make sure "		     "iscsi is loaded",		     ISCSI_DEVICE);		sleep(5);	}	do {		rv = ioctl_establish_session(nbp);		if (rv != 0) {			printf("ISCSI_ESTABLISH_SESSION ioctl for %s failed, "			       "returned from kernel with rv %d",			       nbp->targetstring, rv);		}	} while (rv != 0);}

⌨️ 快捷键说明

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