Ejemplo n.º 1
0
/*
 * NFS mount the kernel directory, and perform a lookup on the
 * kernel file.
 *
 * Places the directory filehandle in global "dirfh"
 * Places the kernel filehandle in global filefh
 *
 * returns 0 on success, nonzero on failure
 */
int
fileinit(struct in_addr ip, char *dirname, char *filename)
{
	int			mount_port;
	char			*readahead_option;
	int			err;
	
	readahead_option = getenv("readahead");
	if (readahead_option)
		kimg_readahead = atoi(readahead_option);
	if (kimg_readahead < 0)
		dprintf("NFS using whole-file readahead\n");
	else if (kimg_readahead > 0)
		dprintf("NFS using %dkb readahead\n", kimg_readahead);

	rpc_init();

	/*
	 * Lookup NFS/MOUNTD ports for ROOT using PORTMAP.
	 */
	nfs_port = rpc_lookup(ip, PROG_NFS, 2);
	mount_port = rpc_lookup(ip, PROG_MOUNT, 1);
	if (nfs_port == -1 || mount_port == -1) {
		printf("Can't get root NFS/MOUNT ports.\n");
		return 1;
	}
	dprintf("fileinit: NFS port = %d, MOUNT port = %d\n",
		nfs_port, mount_port);

	/*
	 * NFS mount the directory.
	 */
	dprintf("Mounting %s ... ", dirname);
	err = nfs_mount(ip, mount_port, dirname, dirfh);
	if (err) {
		printf("Can't mount filesystem: %s.\n", nfs_strerror(err));
		return 1;
	}
	dprintf("done\n");

	/*
	 * Lookup the file.
	 */
	dprintf("Looking up %s ... ", filename);
	err = nfs_lookup(ip, nfs_port, dirfh, filename, filefh);
	if (err) {
		printf("Can't lookup %s: %s.\n", filename, nfs_strerror(err));
		return 1;
	}
	dprintf("done\n");

	/* Stash ipaddr for subsequent calls */
	ipaddr.s_addr = ip.s_addr;

	return 0;
}
Ejemplo n.º 2
0
rpc_export_t* find_rpc_export(char* name, int flags)
{
	return rpc_lookup((char*)name, strlen(name));
}
Ejemplo n.º 3
0
/**************************************************************************
NFS - Download extended BOOTP data, or kernel image from NFS server
**************************************************************************/
int nfs(const char *name, int (*fnc)(unsigned char *, unsigned int, unsigned int, int))
{
	static int recursion = 0;
	int sport;
	int err, namelen = strlen(name);
	char dirname[300], *fname;
	char dirfh[NFS_FHSIZE];		/* file handle of directory */
	char filefh[NFS_FHSIZE];	/* file handle of kernel image */
	unsigned int block;
	int rlen, size, offs, len;
	struct rpc_t *rpc;

	rx_qdrain();

	sport = oport++;
	if (oport > START_OPORT+OPORT_SWEEP) {
		oport = START_OPORT;
	}
	if ( name != dirname ) {
		memcpy(dirname, name, namelen + 1);
	}
	recursion = 0;
nfssymlink:
	if ( recursion > NFS_MAXLINKDEPTH ) {
		printf ( "\nRecursion: More than %d symlinks followed. Abort.\n", NFS_MAXLINKDEPTH );
		return	0;
	}
	recursion++;
	fname = dirname + (namelen - 1);
	while (fname >= dirname) {
		if (*fname == '/') {
			*fname = '\0';
			fname++;
			break;
		}
		fname--;
	}
	if (fname < dirname) {
		printf("can't parse file name %s\n", name);
		return 0;
	}

	if (mount_port == -1) {
		mount_port = rpc_lookup(ARP_SERVER, PROG_MOUNT, 1, sport);
	}
	if (nfs_port == -1) {
		nfs_port = rpc_lookup(ARP_SERVER, PROG_NFS, 2, sport);
	}
	if (nfs_port == -1 || mount_port == -1) {
		printf("can't get nfs/mount ports from portmapper\n");
		return 0;
	}


	err = nfs_mount(ARP_SERVER, mount_port, dirname, dirfh, sport);
	if (err) {
		printf("mounting %s: ", dirname);
		nfs_printerror(err);
		/* just to be sure... */
		nfs_umountall(ARP_SERVER);
		return 0;
	}

	err = nfs_lookup(ARP_SERVER, nfs_port, dirfh, fname, filefh, sport);
	if (err) {
		printf("looking up %s: ", fname);
		nfs_printerror(err);
		nfs_umountall(ARP_SERVER);
		return 0;
	}

	offs = 0;
	block = 1;	/* blocks are numbered starting from 1 */
	size = -1;	/* will be set properly with the first reply */
	len = NFS_READ_SIZE;	/* first request is always full size */
	do {
		err = nfs_read(ARP_SERVER, nfs_port, filefh, offs, len, sport);
                if ((err <= -NFSERR_ISDIR)&&(err >= -NFSERR_INVAL) && (offs == 0)) {
			// An error occured. NFS servers tend to sending
			// errors 21 / 22 when symlink instead of real file
			// is requested. So check if it's a symlink!
			block = nfs_readlink(ARP_SERVER, nfs_port, dirfh, dirname,
			                filefh, sport);
			if ( 0 == block ) {
				printf("\nLoading symlink:%s ..",dirname);
				goto nfssymlink;
			}
			nfs_printerror(err);
			nfs_umountall(ARP_SERVER);
			return 0;
		}
		if (err) {
			printf("reading at offset %d: ", offs);
			nfs_printerror(err);
			nfs_umountall(ARP_SERVER);
			return 0;
		}

		rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];

		/* size must be found out early to allow EOF detection */
		if (size == -1) {
			size = ntohl(rpc->u.reply.data[6]);
		}
		rlen = ntohl(rpc->u.reply.data[18]);
		if (rlen > len) {
			rlen = len;	/* shouldn't happen...  */
		}

		err = fnc((char *)&rpc->u.reply.data[19], block, rlen,
			(offs+rlen == size));
		if (err <= 0) {
			nfs_umountall(ARP_SERVER);
			return err;
		}

		block++;
		offs += rlen;
		/* last request is done with matching requested read size */
		if (size-offs < NFS_READ_SIZE) {
			len = size-offs;
		}
	} while (len != 0);
	/* len == 0 means that all the file has been read */
	return 1;
}