Пример #1
0
int
tftp_open(char *path, struct open_file *f)
{
	struct tftp_handle *tftpfile;
	struct iodesc  *io;
	int             res;

	tftpfile = (struct tftp_handle *) alloc(sizeof(*tftpfile));
	if (tftpfile == NULL)
		return ENOMEM;

	tftpfile->iodesc = io = socktodesc(*(int *) (f->f_devdata));
	io->destip = servip;
	tftpfile->off = 0;
	tftpfile->path = path;	/* XXXXXXX we hope it's static */

	res = tftp_makereq(tftpfile);

	if (res) {
		free(tftpfile, sizeof(*tftpfile));
		return res;
	}
	f->f_fsdata = (void *) tftpfile;
	return 0;
}
Пример #2
0
/*
 * nfs_mount - mount this nfs filesystem to a host
 * On error, return non-zero and set errno.
 */
int
nfs_mount(int sock, struct in_addr ip, char *path)
{
	struct iodesc *desc;
	struct nfsv2_fattrs *fa;

	if (!(desc = socktodesc(sock))) {
		errno = EINVAL;
		return(-1);
	}

	/* Bind to a reserved port. */
	desc->myport = htons(--rpc_port);
	desc->destip = ip;
	if (nfs_getrootfh(desc, path, nfs_root_node.fh))
		return (-1);
	nfs_root_node.iodesc = desc;
	/* Fake up attributes for the root dir. */
	fa = &nfs_root_node.fa;
	fa->fa_type  = htonl(NFDIR);
	fa->fa_mode  = htonl(0755);
	fa->fa_nlink = htonl(2);

#ifdef NFS_DEBUG
	if (debug)
		printf("nfs_mount: got fh for %s\n", path);
#endif

	return(0);
}
Пример #3
0
int
net_open(struct open_file *f, ...)
{
	char		*fname;
	char		**file;
	struct iodesc	*s;
	va_list		ap;

	va_start(ap, f);
	fname = va_arg(ap, char *);
	file = va_arg(ap, char **);
	va_end(ap);

	f->f_devdata = &netdev_sock;
	netdev_sock = netif_open(NULL);

	bootfile[0] = '\0';
	if (bootopts.b_flags & B_F_USE_BOOTP) {
		s = socktodesc(netdev_sock);
		bootp(netdev_sock);
		if (fname[0] != '\0')
			strlcpy(bootfile, fname, sizeof bootfile);
	} else {
		s = socktodesc(netdev_sock);

		servip = s->destip = bootopts.b_remote_ip;
		myip = s->myip = bootopts.b_local_ip;
		netmask = bootopts.b_netmask;
		gateip = bootopts.b_gate_ip;

		if (fname[0] == '\0') {
			printf("no boot filename\n");
			netif_close(netdev_sock);
			return EIO;
		}
		strlcpy(bootfile, fname, sizeof bootfile);
	}

	*file = bootfile;

	return 0;
}
Пример #4
0
/* Fetch required bootp information */
void
bootp(int sock)
{
	struct iodesc *d;
	struct bootp *bp;
	struct {
		u_char header[HEADER_SIZE];
		struct bootp wbootp;
	} wbuf;
	struct {
		u_char header[HEADER_SIZE];
		struct bootp rbootp;
	} rbuf;

#ifdef BOOTP_DEBUG
	if (debug)
		printf("bootp: socket=%d\n", sock);
#endif
	if (!bot)
		bot = getsecs();

	if (!(d = socktodesc(sock))) {
		printf("bootp: bad socket. %d\n", sock);
		return;
	}
#ifdef BOOTP_DEBUG
	if (debug)
		printf("bootp: d=%x\n", (u_int)d);
#endif

	bp = &wbuf.wbootp;
	bzero(bp, sizeof(*bp));

	bp->bp_op = BOOTREQUEST;
	bp->bp_htype = HTYPE_ETHERNET;	/* 10Mb Ethernet (48 bits) */
	bp->bp_hlen = 6;
	bp->bp_xid = htonl(d->xid);
	MACPY(d->myea, bp->bp_chaddr);
	bzero(bp->bp_file, sizeof(bp->bp_file));
	bcopy(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048));

	d->myip = myip;
	d->myport = htons(IPPORT_BOOTPC);
	d->destip.s_addr = INADDR_BROADCAST;
	d->destport = htons(IPPORT_BOOTPS);

	(void)sendrecv(d,
	    bootpsend, bp, sizeof(*bp),
	    bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp));

	/* Bump xid so next request will be unique. */
	++d->xid;
}
Пример #5
0
static int
tftp_open(const char *path, struct open_file *f)
{
	struct tftp_handle *tftpfile;
	struct iodesc  *io;
	int             res;

	if (strcmp(f->f_dev->dv_name, "net") != 0) {
#ifdef __i386__
		if (strcmp(f->f_dev->dv_name, "pxe") != 0)
			return (EINVAL);
#else
		return (EINVAL);
#endif
	}

	if (is_open)
		return (EBUSY);

	tftpfile = (struct tftp_handle *) malloc(sizeof(*tftpfile));
	if (!tftpfile)
		return (ENOMEM);

	memset(tftpfile, 0, sizeof(*tftpfile));
	tftpfile->tftp_blksize = TFTP_REQUESTED_BLKSIZE;
	tftpfile->iodesc = io = socktodesc(*(int *) (f->f_devdata));
	if (io == NULL)
		return (EINVAL);

	io->destip = servip;
	tftpfile->off = 0;
	tftpfile->path = strdup(path);
	if (tftpfile->path == NULL) {
	    free(tftpfile);
	    return(ENOMEM);
	}

	res = tftp_makereq(tftpfile);

	if (res) {
		free(tftpfile->path);
		free(tftpfile);
		return (res);
	}
	f->f_fsdata = (void *) tftpfile;
	is_open = 1;
	return (0);
}
Пример #6
0
static int 
tftp_open(const char *path, struct open_file *f)
{
	struct tftp_handle *tftpfile;
	struct iodesc  *io;
	int             res;

	/* Avoid trying out tftp_open for disk devices in the EFI loader */
#ifndef __i386__
	if (strcmp(f->f_dev->dv_name, "net") != 0)
		return (EINVAL);
#endif

	tftpfile = (struct tftp_handle *) malloc(sizeof(*tftpfile));
	if (!tftpfile)
		return (ENOMEM);

	tftpfile->iodesc = io = socktodesc(*(int *) (f->f_devdata));
	if (io == NULL) {
		free(tftpfile);
		return (EINVAL);
	}

	io->destip = servip;
	tftpfile->off = 0;
	tftpfile->path = strdup(path);
	if (tftpfile->path == NULL) {
	    free(tftpfile);
	    return(ENOMEM);
	}

	res = tftp_makereq(tftpfile);

	if (res) {
		free(tftpfile->path);
		free(tftpfile);
		return (res);
	}
	f->f_fsdata = (void *) tftpfile;
	return (0);
}
Пример #7
0
/*
 * Called by devopen after it sets f->f_dev to our devsw entry.
 * This opens the low-level device and sets f->f_devdata.
 * This is declared with variable arguments...
 */
static int
net_open(struct open_file *f, ...)
{
	char temp[FNAME_SIZE];
	struct iodesc *d;
	va_list args;
	char *devname;		/* Device part of file name (or NULL). */
	int error = 0;

	va_start(args, f);
	devname = va_arg(args, char*);
	va_end(args);

#ifdef	NETIF_OPEN_CLOSE_ONCE
	/* Before opening another interface, close the previous one first. */
	if (netdev_sock >= 0 && strcmp(devname, netdev_name) != 0)
		net_cleanup();
#endif

	/* On first open, do netif open, mount, etc. */
	if (netdev_opens == 0) {
		/* Find network interface. */
		if (netdev_sock < 0) {
			netdev_sock = netif_open(devname);
			if (netdev_sock < 0) {
				printf("net_open: netif_open() failed\n");
				return (ENXIO);
			}
			netdev_name = strdup(devname);
#ifdef	NETIF_DEBUG
			if (debug)
				printf("net_open: netif_open() succeeded\n");
#endif
		}
		/*
		 * If network params were not set by netif_open(), try to get
		 * them via bootp, rarp, etc.
		 */
		if (rootip.s_addr == 0) {
			/* Get root IP address, and path, etc. */
			error = net_getparams(netdev_sock);
			if (error) {
				/* getparams makes its own noise */
				free(netdev_name);
				netif_close(netdev_sock);
				netdev_sock = -1;
				return (error);
			}
		}
		/*
		 * Set the variables required by the kernel's nfs_diskless
		 * mechanism.  This is the minimum set of variables required to
		 * mount a root filesystem without needing to obtain additional
		 * info from bootp or other sources.
		 */
		d = socktodesc(netdev_sock);
		sprintf(temp, "%6D", d->myea, ":");
		setenv("boot.netif.hwaddr", temp, 1);
		setenv("boot.netif.ip", inet_ntoa(myip), 1);
		setenv("boot.netif.netmask", intoa(netmask), 1);
		setenv("boot.netif.gateway", inet_ntoa(gateip), 1);
		setenv("boot.nfsroot.server", inet_ntoa(rootip), 1);
		setenv("boot.nfsroot.path", rootpath, 1);
	}
	netdev_opens++;
	f->f_devdata = &netdev_sock;
	return (error);
}
Пример #8
0
int
netmountroot(struct open_file *f, char *devname)
{
	int error;
	struct iodesc *d;

#ifdef DEBUG
	printf("netmountroot: %s\n", devname);
#endif

	if (netio_ask) {
 get_my_ip:
		printf("My IP address? ");
		bzero(input_line, sizeof(input_line));
		gets(input_line);
		if ((myip.s_addr = inet_addr(input_line)) ==
		    htonl(INADDR_NONE)) {
			printf("invalid IP address: %s\n", input_line);
			goto get_my_ip;
		}

 get_my_netmask:
		printf("My netmask? ");
		bzero(input_line, sizeof(input_line));
		gets(input_line);
		if ((netmask = inet_addr(input_line)) ==
		    htonl(INADDR_NONE)) {
			printf("invalid netmask: %s\n", input_line);
			goto get_my_netmask;
		}

 get_my_gateway:
		printf("My gateway? ");
		bzero(input_line, sizeof(input_line));
		gets(input_line);
		if ((gateip.s_addr = inet_addr(input_line)) ==
		    htonl(INADDR_NONE)) {
			printf("invalid IP address: %s\n", input_line);
			goto get_my_gateway;
		}

 get_server_ip:
		printf("Server IP address? ");
		bzero(input_line, sizeof(input_line));
		gets(input_line);
		if ((rootip.s_addr = inet_addr(input_line)) ==
		    htonl(INADDR_NONE)) {
			printf("invalid IP address: %s\n", input_line);
			goto get_server_ip;
		}

 get_server_path:
		printf("Server path? ");
		bzero(rootpath, sizeof(rootpath));
		gets(rootpath);
		if (rootpath[0] == '\0' || rootpath[0] == '\n')
			goto get_server_path;

		if ((d = socktodesc(netdev_sock)) == NULL)
			return (EMFILE);

		d->myip = myip;

		goto do_nfs_mount;
	}

	/*
	 * Get info for NFS boot: our IP address, our hostname,
	 * server IP address, and our root path on the server.
	 * There are two ways to do this:  The old, Sun way,
	 * and the more modern, BOOTP way. (RFC951, RFC1048)
	 */

#ifdef	SUN_BOOTPARAMS
	/* Get boot info using RARP and Sun bootparams. */

	/* Get our IP address.  (rarp.c) */
	if (rarp_getipaddress(netdev_sock) == -1)
		return (errno);

	printf("boot: client IP address: %s\n", inet_ntoa(myip));

	/* Get our hostname, server IP address. */
	if (bp_whoami(netdev_sock))
		return (errno);

	printf("boot: client name: %s\n", hostname);

	/* Get the root pathname. */
	if (bp_getfile(netdev_sock, "root", &rootip, rootpath))
		return (errno);

#else

	/* Get boot info using BOOTP way. (RFC951, RFC1048) */
	bootp(netdev_sock);

	printf("Using IP address: %s\n", inet_ntoa(myip));

	printf("myip: %s (%s)", hostname, inet_ntoa(myip));
	if (gateip)
		printf(", gateip: %s", inet_ntoa(gateip));
	if (mask)
		printf(", mask: %s", intoa(netmask));
	printf("\n");

#endif /* SUN_BOOTPARAMS */

	printf("root addr=%s path=%s\n", inet_ntoa(rootip), rootpath);

 do_nfs_mount:
	/* Get the NFS file handle (mount). */
	error = nfs_mount(netdev_sock, rootip, rootpath);

	return (error);
}
Пример #9
0
/* Fetch required bootp infomation */
void
bootp(int sock, int flag)
{
	struct iodesc *d;
	struct bootp *bp;
	struct {
		u_char header[HEADER_SIZE];
		struct bootp wbootp;
	} wbuf;
	struct {
		u_char header[HEADER_SIZE];
		struct bootp rbootp;
	} rbuf;

#ifdef BOOTP_DEBUG
 	if (debug)
		printf("bootp: socket=%d\n", sock);
#endif
	if (!bot)
		bot = getsecs();
	
	if (!(d = socktodesc(sock))) {
		printf("bootp: bad socket. %d\n", sock);
		return;
	}
#ifdef BOOTP_DEBUG
 	if (debug)
		printf("bootp: d=%lx\n", (long)d);
#endif

	bp = &wbuf.wbootp;
	bzero(bp, sizeof(*bp));

	bp->bp_op = BOOTREQUEST;
	bp->bp_htype = 1;		/* 10Mb Ethernet (48 bits) */
	bp->bp_hlen = 6;
	bp->bp_xid = htonl(d->xid);
	MACPY(d->myea, bp->bp_chaddr);
	strncpy(bp->bp_file, bootfile, sizeof(bp->bp_file));
	bcopy(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048));
#ifdef SUPPORT_DHCP
	bp->bp_vend[4] = TAG_DHCP_MSGTYPE;
	bp->bp_vend[5] = 1;
	bp->bp_vend[6] = DHCPDISCOVER;

	/*
	 * If we are booting from PXE, we want to send the string
	 * 'PXEClient' to the DHCP server so you have the option of
	 * only responding to PXE aware dhcp requests.
	 */
	if (flag & BOOTP_PXE) {
		bp->bp_vend[7] = TAG_CLASSID;
		bp->bp_vend[8] = 9;
		bcopy("PXEClient", &bp->bp_vend[9], 9);
		bp->bp_vend[18] = TAG_PARAM_REQ;
		bp->bp_vend[19] = 7;
		bp->bp_vend[20] = TAG_ROOTPATH;
		bp->bp_vend[21] = TAG_HOSTNAME;
		bp->bp_vend[22] = TAG_SWAPSERVER;
		bp->bp_vend[23] = TAG_GATEWAY;
		bp->bp_vend[24] = TAG_SUBNET_MASK;
		bp->bp_vend[25] = TAG_INTF_MTU;
		bp->bp_vend[26] = TAG_SERVERID;
		bp->bp_vend[27] = TAG_END;
	} else
		bp->bp_vend[7] = TAG_END;
#else
	bp->bp_vend[4] = TAG_END;
#endif

	d->myip.s_addr = INADDR_ANY;
	d->myport = htons(IPPORT_BOOTPC);
	d->destip.s_addr = INADDR_BROADCAST;
	d->destport = htons(IPPORT_BOOTPS);

#ifdef SUPPORT_DHCP
	expected_dhcpmsgtype = DHCPOFFER;
	dhcp_ok = 0;
#endif

	if(sendrecv(d,
		    bootpsend, bp, sizeof(*bp),
		    bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
	   == -1) {
	    printf("bootp: no reply\n");
	    return;
	}

#ifdef SUPPORT_DHCP
	if(dhcp_ok) {
		u_int32_t leasetime;
		bp->bp_vend[6] = DHCPREQUEST;
		bp->bp_vend[7] = TAG_REQ_ADDR;
		bp->bp_vend[8] = 4;
		bcopy(&rbuf.rbootp.bp_yiaddr, &bp->bp_vend[9], 4);
		bp->bp_vend[13] = TAG_SERVERID;
		bp->bp_vend[14] = 4;
		bcopy(&dhcp_serverip.s_addr, &bp->bp_vend[15], 4);
		bp->bp_vend[19] = TAG_LEASETIME;
		bp->bp_vend[20] = 4;
		leasetime = htonl(300);
		bcopy(&leasetime, &bp->bp_vend[21], 4);
		if (flag & BOOTP_PXE) {
			bp->bp_vend[25] = TAG_CLASSID;
			bp->bp_vend[26] = 9;
			bcopy("PXEClient", &bp->bp_vend[27], 9);
			bp->bp_vend[36] = TAG_END;
		} else
			bp->bp_vend[25] = TAG_END;

		expected_dhcpmsgtype = DHCPACK;

		if(sendrecv(d,
			    bootpsend, bp, sizeof(*bp),
			    bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
		   == -1) {
			printf("DHCPREQUEST failed\n");
			return;
		}
	}
#endif

	myip = d->myip = rbuf.rbootp.bp_yiaddr;
	servip = rbuf.rbootp.bp_siaddr;
	if(rootip.s_addr == INADDR_ANY) rootip = servip;
	bcopy(rbuf.rbootp.bp_file, bootfile, sizeof(bootfile));
	bootfile[sizeof(bootfile) - 1] = '\0';

	if (!netmask) {
		if (IN_CLASSA(ntohl(myip.s_addr)))
			netmask = htonl(IN_CLASSA_NET);
		else if (IN_CLASSB(ntohl(myip.s_addr)))
			netmask = htonl(IN_CLASSB_NET);
		else
			netmask = htonl(IN_CLASSC_NET);
#ifdef BOOTP_DEBUG
		if (debug)
			printf("'native netmask' is %s\n", intoa(netmask));
#endif
	}

#ifdef BOOTP_DEBUG
	if (debug)
		printf("mask: %s\n", intoa(netmask));
#endif

	/* We need a gateway if root is on a different net */
	if (!SAMENET(myip, rootip, netmask)) {
#ifdef BOOTP_DEBUG
		if (debug)
			printf("need gateway for root ip\n");
#endif
	}

	/* Toss gateway if on a different net */
	if (!SAMENET(myip, gateip, netmask)) {
#ifdef BOOTP_DEBUG
		if (debug)
			printf("gateway ip (%s) bad\n", inet_ntoa(gateip));
#endif
		gateip.s_addr = 0;
	}

	/* Bump xid so next request will be unique. */
	++d->xid;
}
Пример #10
0
/*
 * Ethernet (Reverse) Address Resolution Protocol (see RFC 903, and 826).
 */
int
rarp_getipaddress(int sock)
{
	struct iodesc *d;
	struct ether_arp *ap;
	struct {
		u_char header[ETHER_SIZE];
		struct {
			struct ether_arp arp;
			u_char pad[18];		/* 60 - sizeof(arp) */
		} data;
	} wbuf;
	struct {
		u_char header[ETHER_SIZE];
		struct {
			struct ether_arp arp;
			u_char pad[24];		/* extra space */
		} data;
	} rbuf;

#ifdef RARP_DEBUG
	if (debug)
		printf("rarp: socket=%d\n", sock);
#endif
	if (!(d = socktodesc(sock))) {
		printf("rarp: bad socket. %d\n", sock);
		return (-1);
	}
#ifdef RARP_DEBUG
	if (debug)
		printf("rarp: d=%x\n", (u_int)d);
#endif

	bzero((char*)&wbuf.data, sizeof(wbuf.data));
	ap = &wbuf.data.arp;
	ap->arp_hrd = htons(ARPHRD_ETHER);
	ap->arp_pro = htons(ETHERTYPE_IP);
	ap->arp_hln = sizeof(ap->arp_sha); /* hardware address length */
	ap->arp_pln = sizeof(ap->arp_spa); /* protocol address length */
	ap->arp_op = htons(ARPOP_REVREQUEST);
	bcopy(d->myea, ap->arp_sha, 6);
	bcopy(d->myea, ap->arp_tha, 6);

	if (sendrecv(d,
	    rarpsend, &wbuf.data, sizeof(wbuf.data),
	    rarprecv, &rbuf.data, sizeof(rbuf.data)) < 0)
	{
		printf("No response for RARP request\n");
		return (-1);
	}

	ap = &rbuf.data.arp;
	bcopy(ap->arp_tpa, (char *)&myip, sizeof(myip));
#if 0
	/* XXX - Can NOT assume this is our root server! */
	bcopy(ap->arp_spa, (char *)&rootip, sizeof(rootip));
#endif

	/* Compute our "natural" netmask. */
	if (IN_CLASSA(myip.s_addr))
		netmask = IN_CLASSA_NET;
	else if (IN_CLASSB(myip.s_addr))
		netmask = IN_CLASSB_NET;
	else
		netmask = IN_CLASSC_NET;

	d->myip = myip;
	return (0);
}
Пример #11
0
/* Fetch required bootp information */
void
bootp(int sock)
{
	struct iodesc *d;
	struct bootp *bp;
	struct {
		u_char header[UDP_TOTAL_HEADER_SIZE];
		struct bootp wbootp;
	} wbuf;
	struct {
		u_char header[UDP_TOTAL_HEADER_SIZE];
		struct bootp rbootp;
	} rbuf;
	unsigned int index;

#ifdef BOOTP_DEBUG
 	if (debug)
		printf("bootp: socket=%d\n", sock);
#endif
	if (!bot)
		bot = getsecs();

	if (!(d = socktodesc(sock))) {
		printf("bootp: bad socket. %d\n", sock);
		return;
	}
#ifdef BOOTP_DEBUG
 	if (debug)
		printf("bootp: d=%lx\n", (long)d);
#endif

	bp = &wbuf.wbootp;
	(void)memset(bp, 0, sizeof(*bp));

	bp->bp_op = BOOTREQUEST;
	bp->bp_htype = 1;		/* 10Mb Ethernet (48 bits) */
	bp->bp_hlen = 6;
	bp->bp_xid = htonl(d->xid);
	MACPY(d->myea, bp->bp_chaddr);
	(void)strncpy((char *)bp->bp_file, bootfile, sizeof(bp->bp_file));
	(void)memcpy(bp->bp_vend, vm_rfc1048, sizeof(vm_rfc1048));
	index = 4;
#ifdef SUPPORT_DHCP
	bp->bp_vend[index++] = TAG_DHCP_MSGTYPE;
	bp->bp_vend[index++] = 1;
	bp->bp_vend[index++] = DHCPDISCOVER;
#endif
	bootp_addvend(&bp->bp_vend[index]);

	d->myip.s_addr = INADDR_ANY;
	d->myport = htons(IPPORT_BOOTPC);
	d->destip.s_addr = INADDR_BROADCAST;
	d->destport = htons(IPPORT_BOOTPS);

#ifdef SUPPORT_DHCP
	expected_dhcpmsgtype = DHCPOFFER;
	dhcp_ok = 0;
#endif

	if (sendrecv(d,
		    bootpsend, bp, sizeof(*bp),
		    bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
	   == -1) {
		printf("bootp: no reply\n");
		return;
	}

#ifdef SUPPORT_DHCP
	if (dhcp_ok) {
		u_int32_t leasetime;
		index = 6;
		bp->bp_vend[index++] = DHCPREQUEST;
		bp->bp_vend[index++] = TAG_REQ_ADDR;
		bp->bp_vend[index++] = 4;
		(void)memcpy(&bp->bp_vend[9], &rbuf.rbootp.bp_yiaddr, 4);
		index += 4;
		bp->bp_vend[index++] = TAG_SERVERID;
		bp->bp_vend[index++] = 4;
		(void)memcpy(&bp->bp_vend[index], &dhcp_serverip.s_addr, 4);
		index += 4;
		bp->bp_vend[index++] = TAG_LEASETIME;
		bp->bp_vend[index++] = 4;
		leasetime = htonl(300);
		(void)memcpy(&bp->bp_vend[index], &leasetime, 4);
		index += 4;
		bootp_addvend(&bp->bp_vend[index]);

		expected_dhcpmsgtype = DHCPACK;

		if (sendrecv(d,
			    bootpsend, bp, sizeof(*bp),
			    bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
		   == -1) {
			printf("DHCPREQUEST failed\n");
			return;
		}
	}
#endif

	myip = d->myip = rbuf.rbootp.bp_yiaddr;
	servip = rbuf.rbootp.bp_siaddr;
	if (rootip.s_addr == INADDR_ANY)
		rootip = servip;
	(void)memcpy(bootfile, rbuf.rbootp.bp_file, sizeof(bootfile));
	bootfile[sizeof(bootfile) - 1] = '\0';

	if (IN_CLASSA(myip.s_addr))
		nmask = IN_CLASSA_NET;
	else if (IN_CLASSB(myip.s_addr))
		nmask = IN_CLASSB_NET;
	else
		nmask = IN_CLASSC_NET;
#ifdef BOOTP_DEBUG
	if (debug)
		printf("'native netmask' is %s\n", intoa(nmask));
#endif

	/* Get subnet (or natural net) mask */
	netmask = nmask;
	if (smask)
		netmask = smask;
#ifdef BOOTP_DEBUG
	if (debug)
		printf("mask: %s\n", intoa(netmask));
#endif

	/* We need a gateway if root is on a different net */
	if (!SAMENET(myip, rootip, netmask)) {
#ifdef BOOTP_DEBUG
		if (debug)
			printf("need gateway for root ip\n");
#endif
	}

	/* Toss gateway if on a different net */
	if (!SAMENET(myip, gateip, netmask)) {
#ifdef BOOTP_DEBUG
		if (debug)
			printf("gateway ip (%s) bad\n", inet_ntoa(gateip));
#endif
		gateip.s_addr = 0;
	}

#ifdef BOOTP_DEBUG
	if (debug) {
		printf("client addr: %s\n", inet_ntoa(myip));
		if (smask)
			printf("subnet mask: %s\n", intoa(smask));
		if (gateip.s_addr != 0)
			printf("net gateway: %s\n", inet_ntoa(gateip));
		printf("server addr: %s\n", inet_ntoa(rootip));
		if (rootpath[0] != '\0')
			printf("server path: %s\n", rootpath);
		if (bootfile[0] != '\0')
			printf("file name: %s\n", bootfile);
	}
#endif

	/* Bump xid so next request will be unique. */
	++d->xid;
}
Пример #12
0
/* Fetch required bootp infomation */
void
bootp(int sock)
{
	void *pkt;
	struct iodesc *d;
	struct bootp *bp;
	struct {
		uchar_t header[HEADER_SIZE];
		struct bootp wbootp;
	} wbuf;
	struct bootp *rbootp;

#ifdef BOOTP_DEBUG
	if (debug)
		printf("bootp: socket=%d\n", sock);
#endif
	if (!bot)
		bot = getsecs();

	if (!(d = socktodesc(sock))) {
		printf("bootp: bad socket. %d\n", sock);
		return;
	}
#ifdef BOOTP_DEBUG
	if (debug)
		printf("bootp: d=%lx\n", (long)d);
#endif

	bp = &wbuf.wbootp;
	bzero(bp, sizeof (*bp));

	bp->bp_op = BOOTREQUEST;
	bp->bp_htype = 1;		/* 10Mb Ethernet (48 bits) */
	bp->bp_hlen = 6;
	bp->bp_xid = htonl(d->xid);
	MACPY(d->myea, bp->bp_chaddr);
	strncpy(bp->bp_file, bootfile, sizeof (bp->bp_file));
	bcopy(vm_rfc1048, bp->bp_vend, sizeof (vm_rfc1048));
#ifdef SUPPORT_DHCP
	bp->bp_vend[4] = TAG_DHCP_MSGTYPE;
	bp->bp_vend[5] = 1;
	bp->bp_vend[6] = DHCPDISCOVER;
	bootp_fill_request(&bp->bp_vend[7]);
#else
	bp->bp_vend[4] = TAG_END;
#endif

	d->myip.s_addr = INADDR_ANY;
	d->myport = htons(IPPORT_BOOTPC);
	d->destip.s_addr = INADDR_BROADCAST;
	d->destport = htons(IPPORT_BOOTPS);

#ifdef SUPPORT_DHCP
	expected_dhcpmsgtype = DHCPOFFER;
	dhcp_ok = 0;
#endif

	if (sendrecv(d, bootpsend, bp, sizeof (*bp),
	    bootprecv, &pkt, (void **)&rbootp, NULL) == -1) {
		printf("bootp: no reply\n");
		return;
	}

#ifdef SUPPORT_DHCP
	if (dhcp_ok) {
		uint32_t leasetime;
		bp->bp_vend[6] = DHCPREQUEST;
		bp->bp_vend[7] = TAG_REQ_ADDR;
		bp->bp_vend[8] = 4;
		bcopy(&rbootp->bp_yiaddr, &bp->bp_vend[9], 4);
		bp->bp_vend[13] = TAG_SERVERID;
		bp->bp_vend[14] = 4;
		bcopy(&dhcp_serverip.s_addr, &bp->bp_vend[15], 4);
		bp->bp_vend[19] = TAG_LEASETIME;
		bp->bp_vend[20] = 4;
		leasetime = htonl(300);
		bcopy(&leasetime, &bp->bp_vend[21], 4);
		bootp_fill_request(&bp->bp_vend[25]);

		expected_dhcpmsgtype = DHCPACK;

		free(pkt);
		if (sendrecv(d, bootpsend, bp, sizeof (*bp),
		    bootprecv, &pkt, (void **)&rbootp, NULL) == -1) {
			printf("DHCPREQUEST failed\n");
			return;
		}
	}
#endif

	myip = d->myip = rbootp->bp_yiaddr;
	servip = rbootp->bp_siaddr;
	if (rootip.s_addr == INADDR_ANY)
		rootip = servip;
	bcopy(rbootp->bp_file, bootfile, sizeof (bootfile));
	bootfile[sizeof (bootfile) - 1] = '\0';

	if (!netmask) {
		if (IN_CLASSA(ntohl(myip.s_addr)))
			netmask = htonl(IN_CLASSA_NET);
		else if (IN_CLASSB(ntohl(myip.s_addr)))
			netmask = htonl(IN_CLASSB_NET);
		else
			netmask = htonl(IN_CLASSC_NET);
#ifdef BOOTP_DEBUG
		if (debug)
			printf("'native netmask' is %s\n", intoa(netmask));
#endif
	}

#ifdef BOOTP_DEBUG
	if (debug)
		printf("mask: %s\n", intoa(netmask));
#endif

	/* We need a gateway if root is on a different net */
	if (!SAMENET(myip, rootip, netmask)) {
#ifdef BOOTP_DEBUG
		if (debug)
			printf("need gateway for root ip\n");
#endif
	}

	/* Toss gateway if on a different net */
	if (!SAMENET(myip, gateip, netmask)) {
#ifdef BOOTP_DEBUG
		if (debug)
			printf("gateway ip (%s) bad\n", inet_ntoa(gateip));
#endif
		gateip.s_addr = 0;
	}

	/* Bump xid so next request will be unique. */
	++d->xid;
	free(pkt);
}
Пример #13
0
static int
net_getparams(int sock)
{
    char buf[MAXHOSTNAMELEN];
    char temp[FNAME_SIZE];
    struct iodesc *d;
    int i;
    n_long smask;

#ifdef	SUPPORT_BOOTP
    /*
     * Try to get boot info using BOOTP.  If we succeed, then
     * the server IP address, gateway, and root path will all
     * be initialized.  If any remain uninitialized, we will
     * use RARP and RPC/bootparam (the Sun way) to get them.
     */
    if (try_bootp)
	bootp(sock, BOOTP_NONE);
    if (myip.s_addr != 0)
	goto exit;
    if (debug)
	printf("net_open: BOOTP failed, trying RARP/RPC...\n");
#endif

    /*
     * Use RARP to get our IP address.  This also sets our
     * netmask to the "natural" default for our address.
     */
    if (rarp_getipaddress(sock)) {
	printf("net_open: RARP failed\n");
	return (EIO);
    }
    printf("net_open: client addr: %s\n", inet_ntoa(myip));

    /* Get our hostname, server IP address, gateway. */
    if (bp_whoami(sock)) {
	printf("net_open: bootparam/whoami RPC failed\n");
	return (EIO);
    }
    printf("net_open: client name: %s\n", hostname);

    /*
     * Ignore the gateway from whoami (unreliable).
     * Use the "gateway" parameter instead.
     */
    smask = 0;
    gateip.s_addr = 0;
    if (bp_getfile(sock, "gateway", &gateip, buf) == 0) {
	/* Got it!  Parse the netmask. */
	smask = ip_convertaddr(buf);
    }
    if (smask) {
	netmask = smask;
	printf("net_open: subnet mask: %s\n", intoa(netmask));
    }
    if (gateip.s_addr)
	printf("net_open: net gateway: %s\n", inet_ntoa(gateip));

    /* Get the root server and pathname. */
    if (bp_getfile(sock, "root", &rootip, rootpath)) {
	printf("net_open: bootparam/getfile RPC failed\n");
	return (EIO);
    }
 exit:
    /*  
     * If present, strip the server's address off of the rootpath
     * before passing it along.  This allows us to be compatible with
     * the kernel's diskless (BOOTP_NFSROOT) booting conventions
     */
    for (i = 0; i < FNAME_SIZE && rootpath[i] != '\0'; i++)
	    if (rootpath[i] == ':')
		    break;
    if (i && i != FNAME_SIZE && rootpath[i] == ':') {
	    rootpath[i++] = '\0';
	    if (inet_addr(&rootpath[0]) != INADDR_NONE)
		    rootip.s_addr = inet_addr(&rootpath[0]);
	    memcpy(&temp[0], &rootpath[i], strlen(&rootpath[i])+1);
	    memcpy(&rootpath[0], &temp[0], strlen(&rootpath[i])+1);	    
    }
    printf("net_open: server addr: %s\n", inet_ntoa(rootip));
    printf("net_open: server path: %s\n", rootpath);	    

    d = socktodesc(sock);
    snprintf(temp, sizeof(temp), "%6D", d->myea, ":");
    setenv("boot.netif.ip", inet_ntoa(myip), 1);
    setenv("boot.netif.netmask", intoa(netmask), 1);
    setenv("boot.netif.gateway", inet_ntoa(gateip), 1);
    setenv("boot.netif.hwaddr", temp, 1);
    setenv("boot.nfsroot.server", inet_ntoa(rootip), 1);
    setenv("boot.nfsroot.path", rootpath, 1);

    return (0);
}
Пример #14
0
/*
 * Open a file.
 * return zero or error number
 */
int
nfs_open(const char *upath, struct open_file *f)
{
	struct iodesc *desc;
	struct nfs_iodesc *currfd;
	char buf[2 * NFS_FHSIZE + 3];
	u_char *fh;
	char *cp;
	int i;
#ifndef NFS_NOSYMLINK
	struct nfs_iodesc *newfd;
	struct nfsv2_fattrs *fa;
	char *ncp;
	int c;
	char namebuf[NFS_MAXPATHLEN + 1];
	char linkbuf[NFS_MAXPATHLEN + 1];
	int nlinks = 0;
#endif
	int error;
	char *path;

#ifdef NFS_DEBUG
 	if (debug)
 	    printf("nfs_open: %s (rootpath=%s)\n", upath, rootpath);
#endif
	if (!rootpath[0]) {
		printf("no rootpath, no nfs\n");
		return (ENXIO);
	}

	/*
	 * This is silly - we should look at dv_type but that value is
	 * arch dependant and we can't use it here.
	 */
#ifndef __i386__
	if (strcmp(f->f_dev->dv_name, "net") != 0)
		return(EINVAL);
#else
	if (strcmp(f->f_dev->dv_name, "pxe") != 0)
		return(EINVAL);
#endif

	if (!(desc = socktodesc(*(int *)(f->f_devdata))))
		return(EINVAL);

	/* Bind to a reserved port. */
	desc->myport = htons(--rpc_port);
	desc->destip = rootip;
	if ((error = nfs_getrootfh(desc, rootpath, nfs_root_node.fh)))
		return (error);
	nfs_root_node.fa.fa_type  = htonl(NFDIR);
	nfs_root_node.fa.fa_mode  = htonl(0755);
	nfs_root_node.fa.fa_nlink = htonl(2);
	nfs_root_node.iodesc = desc;

	fh = &nfs_root_node.fh[0];
	buf[0] = 'X';
	cp = &buf[1];
	for (i = 0; i < NFS_FHSIZE; i++, cp += 2)
		sprintf(cp, "%02x", fh[i]);
	sprintf(cp, "X");
	setenv("boot.nfsroot.server", inet_ntoa(rootip), 1);
	setenv("boot.nfsroot.path", rootpath, 1);
	setenv("boot.nfsroot.nfshandle", buf, 1);

	/* Allocate file system specific data structure */
	currfd = malloc(sizeof(*newfd));
	if (currfd == NULL) {
		error = ENOMEM;
		goto out;
	}

#ifndef NFS_NOSYMLINK
	bcopy(&nfs_root_node, currfd, sizeof(*currfd));
	newfd = 0;

	cp = path = strdup(upath);
	if (path == NULL) {
	    error = ENOMEM;
	    goto out;
	}
	while (*cp) {
		/*
		 * Remove extra separators
		 */
		while (*cp == '/')
			cp++;

		if (*cp == '\0')
			break;
		/*
		 * Check that current node is a directory.
		 */
		if (currfd->fa.fa_type != htonl(NFDIR)) {
			error = ENOTDIR;
			goto out;
		}

		/* allocate file system specific data structure */
		newfd = malloc(sizeof(*newfd));
		newfd->iodesc = currfd->iodesc;

		/*
		 * Get next component of path name.
		 */
		{
			int len = 0;

			ncp = cp;
			while ((c = *cp) != '\0' && c != '/') {
				if (++len > NFS_MAXNAMLEN) {
					error = ENOENT;
					goto out;
				}
				cp++;
			}
			*cp = '\0';
		}

		/* lookup a file handle */
		error = nfs_lookupfh(currfd, ncp, newfd);
		*cp = c;
		if (error)
			goto out;

		/*
		 * Check for symbolic link
		 */
		if (newfd->fa.fa_type == htonl(NFLNK)) {
			int link_len, len;

			error = nfs_readlink(newfd, linkbuf);
			if (error)
				goto out;

			link_len = strlen(linkbuf);
			len = strlen(cp);

			if (link_len + len > MAXPATHLEN
			    || ++nlinks > MAXSYMLINKS) {
				error = ENOENT;
				goto out;
			}

			bcopy(cp, &namebuf[link_len], len + 1);
			bcopy(linkbuf, namebuf, link_len);

			/*
			 * If absolute pathname, restart at root.
			 * If relative pathname, restart at parent directory.
			 */
			cp = namebuf;
			if (*cp == '/')
				bcopy(&nfs_root_node, currfd, sizeof(*currfd));

			free(newfd);
			newfd = 0;

			continue;
		}

		free(currfd);
		currfd = newfd;
		newfd = 0;
	}

	error = 0;

out:
	free(newfd);
	free(path);
#else
        currfd->iodesc = desc;

        error = nfs_lookupfh(&nfs_root_node, upath, currfd);
#endif
	if (!error) {
		currfd->off = 0;
		f->f_fsdata = (void *)currfd;
		return (0);
	}

#ifdef NFS_DEBUG
	if (debug)
		printf("nfs_open: %s lookupfh failed: %s\n",
		    path, strerror(error));
#endif
	free(currfd);

	return (error);
}
Пример #15
0
/*
 * RPC: bootparam/getfile
 * Given client name and file "key", get:
 *	server name
 *	server IP address
 *	server pathname
 */
int
bp_getfile(int sockfd, char *key, struct in_addr *serv_addr, char *pathname)
{
	struct {
		n_long	h[RPC_HEADER_WORDS];
		n_long  d[64];
	} sdata;
	struct {
		n_long	h[RPC_HEADER_WORDS];
		n_long  d[128];
	} rdata;
	char serv_name[FNAME_SIZE];
	char *send_tail, *recv_head;
	/* misc... */
	struct iodesc *d;
	int sn_len, path_len, rlen;

	if (!(d = socktodesc(sockfd))) {
		RPC_PRINTF(("bp_getfile: bad socket. %d\n", sockfd));
		return (-1);
	}

	send_tail = (char *)sdata.d;
	recv_head = (char *)rdata.d;

	/*
	 * Build request message.
	 */

	/* client name (hostname) */
	if (xdr_string_encode(&send_tail, hostname, hostnamelen)) {
		RPC_PRINTF(("bp_getfile: bad client\n"));
		return (-1);
	}

	/* key name (root or swap) */
	if (xdr_string_encode(&send_tail, key, strlen(key))) {
		RPC_PRINTF(("bp_getfile: bad key\n"));
		return (-1);
	}

	/* RPC: bootparam/getfile */
	d->myport = htons(--rpc_port);
	d->destip   = bp_server_addr;
	/* rpc_call will set d->destport */

	rlen = rpc_call(d,
		BOOTPARAM_PROG, BOOTPARAM_VERS, BOOTPARAM_GETFILE,
		sdata.d, send_tail - (char *)sdata.d,
		rdata.d, sizeof(rdata.d));
	if (rlen < 4) {
		RPC_PRINTF(("bp_getfile: short reply\n"));
		errno = EBADRPC;
		return (-1);
	}
	recv_head = (char *)rdata.d;

	/*
	 * Parse result message.
	 */

	/* server name */
	sn_len = FNAME_SIZE-1;
	if (xdr_string_decode(&recv_head, serv_name, &sn_len)) {
		RPC_PRINTF(("bp_getfile: bad server name\n"));
		return (-1);
	}

	/* server IP address (mountd/NFS) */
	if (xdr_inaddr_decode(&recv_head, serv_addr)) {
		RPC_PRINTF(("bp_getfile: bad server addr\n"));
		return (-1);
	}

	/* server pathname */
	path_len = MAXPATHLEN-1;
	if (xdr_string_decode(&recv_head, pathname, &path_len)) {
		RPC_PRINTF(("bp_getfile: bad server path\n"));
		return (-1);
	}

	/* success */
	return(0);
}
Пример #16
0
/*
 * RPC: bootparam/whoami
 * Given client IP address, get:
 *	client name	(hostname)
 *	domain name (domainname)
 *	gateway address
 *
 * The hostname and domainname are set here for convenience.
 *
 * Note - bpsin is initialized to the broadcast address,
 * and will be replaced with the bootparam server address
 * after this call is complete.  Have to use PMAP_PROC_CALL
 * to make sure we get responses only from a servers that
 * know about us (don't want to broadcast a getport call).
 */
int
bp_whoami(int sockfd)
{
	/* RPC structures for PMAPPROC_CALLIT */
	struct args {
		u_int32_t prog;
		u_int32_t vers;
		u_int32_t proc;
		u_int32_t arglen;
		struct xdr_inaddr xina;
	} *args;
	struct repl {
		u_int16_t _pad;
		u_int16_t port;
		u_int32_t encap_len;
		/* encapsulated data here */
		n_long  capsule[64];
	} *repl;
	struct {
		n_long	h[RPC_HEADER_WORDS];
		struct args d;
	} sdata;
	struct {
		n_long	h[RPC_HEADER_WORDS];
		struct repl d;
	} rdata;
	char *send_tail, *recv_head;
	struct iodesc *d;
	int len, x;

	RPC_PRINTF(("bp_whoami: myip=%s\n", inet_ntoa(myip)));

	if (!(d = socktodesc(sockfd))) {
		RPC_PRINTF(("bp_whoami: bad socket. %d\n", sockfd));
		return (-1);
	}
	args = &sdata.d;
	repl = &rdata.d;

	/*
	 * Build request args for PMAPPROC_CALLIT.
	 */
	args->prog = htonl(BOOTPARAM_PROG);
	args->vers = htonl(BOOTPARAM_VERS);
	args->proc = htonl(BOOTPARAM_WHOAMI);
	args->arglen = htonl(sizeof(struct xdr_inaddr));
	send_tail = (char *)&args->xina;

	/*
	 * append encapsulated data (client IP address)
	 */
	if (xdr_inaddr_encode(&send_tail, myip))
		return (-1);

	/* RPC: portmap/callit */
	d->myport = htons(--rpc_port);
	d->destip.s_addr = INADDR_BROADCAST;	/* XXX: subnet bcast? */
	/* rpc_call will set d->destport */

	len = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_CALLIT,
	    args, send_tail - (char *)args,
	    repl, sizeof(*repl));
	if (len < 8) {
		printf("bootparamd: 'whoami' call failed\n");
		return (-1);
	}

	/* Save bootparam server address (from IP header). */
	rpc_fromaddr(repl, &bp_server_addr, &bp_server_port);

	/*
	 * Note that bp_server_port is now 111 due to the
	 * indirect call (using PMAPPROC_CALLIT), so get the
	 * actual port number from the reply data.
	 */
	bp_server_port = repl->port;

	RPC_PRINTF(("bp_whoami: server at %s:%d\n",
	    inet_ntoa(bp_server_addr), ntohs(bp_server_port)));

	/* We have just done a portmap call, so cache the portnum. */
	rpc_pmap_putcache(bp_server_addr, BOOTPARAM_PROG, BOOTPARAM_VERS,
	    (int)ntohs(bp_server_port));

	/*
	 * Parse the encapsulated results from bootparam/whoami
	 */
	x = ntohl(repl->encap_len);
	if (len < x) {
		printf("bp_whoami: short reply, %d < %d\n", len, x);
		return (-1);
	}
	recv_head = (char *)repl->capsule;

	/* client name */
	hostnamelen = MAXHOSTNAMELEN-1;
	if (xdr_string_decode(&recv_head, hostname, &hostnamelen)) {
		RPC_PRINTF(("bp_whoami: bad hostname\n"));
		return (-1);
	}

	/* domain name */
	domainnamelen = MAXHOSTNAMELEN-1;
	if (xdr_string_decode(&recv_head, domainname, &domainnamelen)) {
		RPC_PRINTF(("bp_whoami: bad domainname\n"));
		return (-1);
	}

	/* gateway address */
	if (xdr_inaddr_decode(&recv_head, &gateip)) {
		RPC_PRINTF(("bp_whoami: bad gateway\n"));
		return (-1);
	}

	/* success */
	return(0);
}