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

📄 nic.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 3 页
字号:
/**************************************************************************Etherboot -  Network Bootstrap ProgramLiterature dealing with the network protocols:	ARP - RFC826	RARP - RFC903        IP - RFC791	UDP - RFC768	BOOTP - RFC951, RFC2132 (vendor extensions)	DHCP - RFC2131, RFC2132 (options)	TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize)	RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper)	NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented)	IGMP - RFC1112, RFC2113, RFC2365, RFC2236, RFC3171**************************************************************************/#include "etherboot.h"#include "nic.h"#include "elf.h" /* FOR EM_CURRENT */struct arptable_t	arptable[MAX_ARP];#if MULTICAST_LEVEL2unsigned long last_igmpv1 = 0;struct igmptable_t	igmptable[MAX_IGMP];#endif/* Currently no other module uses rom, but it is available */struct rom_info		rom;static unsigned long	netmask;/* Used by nfs.c */char *hostname = "";int hostnamelen = 0;static uint32_t xid;unsigned char *end_of_rfc1533 = NULL;static int vendorext_isvalid;static const unsigned char vendorext_magic[] = {0xE4,0x45,0x74,0x68}; /* 銭th */static const unsigned char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };static const in_addr zeroIP = { 0L };struct bootpd_t bootp_data;#ifdef	NO_DHCP_SUPPORTstatic unsigned char    rfc1533_cookie[5] = { RFC1533_COOKIE, RFC1533_END };#else	/* !NO_DHCP_SUPPORT */static int dhcp_reply;static in_addr dhcp_server = { 0L };static in_addr dhcp_addr = { 0L };static unsigned char	rfc1533_cookie[] = { RFC1533_COOKIE };#define DHCP_MACHINE_INFO_SIZE (sizeof dhcp_machine_info)static unsigned char dhcp_machine_info[] = {	/* Our enclosing DHCP tag */	RFC1533_VENDOR_ETHERBOOT_ENCAP, 11,	/* Our boot device */	RFC1533_VENDOR_NIC_DEV_ID, 5, PCI_BUS_TYPE, 0, 0, 0, 0,	/* Our current architecture */	RFC1533_VENDOR_ARCH, 2, EM_CURRENT & 0xff, (EM_CURRENT >> 8) & 0xff,#ifdef EM_CURRENT_64	/* The 64bit version of our current architecture */	RFC1533_VENDOR_ARCH, 2, EM_CURRENT_64 & 0xff, (EM_CURRENT_64 >> 8) & 0xff,#undef DHCP_MACHINE_INFO_SIZE#define DHCP_MACHINE_INFO_SIZE (sizeof(dhcp_machine_info) - (EM_CURRENT_64_PRESENT? 0: 4))#endif /* EM_CURRENT_64 */};static const unsigned char dhcpdiscover[] = {	RFC2132_MSG_TYPE,1,DHCPDISCOVER,	RFC2132_MAX_SIZE,2,	/* request as much as we can */	ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,	RFC2132_VENDOR_CLASS_ID,13,'E','t','h','e','r','b','o','o','t',	'-',VERSION_MAJOR+'0','.',VERSION_MINOR+'0',	RFC2132_PARAM_LIST,4,RFC1533_NETMASK,RFC1533_GATEWAY,	RFC1533_HOSTNAME,RFC1533_VENDOR};static const unsigned char dhcprequest [] = {	RFC2132_MSG_TYPE,1,DHCPREQUEST,	RFC2132_SRV_ID,4,0,0,0,0,	RFC2132_REQ_ADDR,4,0,0,0,0,	RFC2132_MAX_SIZE,2,	/* request as much as we can */	ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,	RFC2132_VENDOR_CLASS_ID,13,'E','t','h','e','r','b','o','o','t',	'-',VERSION_MAJOR+'0','.',VERSION_MINOR+'0',	/* request parameters */	RFC2132_PARAM_LIST,#ifdef	IMAGE_FREEBSD	/* 5 standard + 7 vendortags + 8 motd + 16 menu items */	5 + 7 + 8 + 16,#else	/* 5 standard + 6 vendortags + 8 motd + 16 menu items */	5 + 6 + 8 + 16,#endif	/* Standard parameters */	RFC1533_NETMASK, RFC1533_GATEWAY,	RFC1533_HOSTNAME,RFC1533_VENDOR,	RFC1533_ROOTPATH,	/* only passed to the booted image */	/* Etherboot vendortags */	RFC1533_VENDOR_MAGIC,	RFC1533_VENDOR_ADDPARM,	RFC1533_VENDOR_ETHDEV,	RFC1533_VENDOR_ETHERBOOT_ENCAP,#ifdef	IMAGE_FREEBSD	RFC1533_VENDOR_HOWTO,	RFC1533_VENDOR_KERNEL_ENV,#endif	RFC1533_VENDOR_MNUOPTS, RFC1533_VENDOR_SELECTION,	/* 8 MOTD entries */	RFC1533_VENDOR_MOTD,	RFC1533_VENDOR_MOTD+1,	RFC1533_VENDOR_MOTD+2,	RFC1533_VENDOR_MOTD+3,	RFC1533_VENDOR_MOTD+4,	RFC1533_VENDOR_MOTD+5,	RFC1533_VENDOR_MOTD+6,	RFC1533_VENDOR_MOTD+7,	/* 16 image entries */	RFC1533_VENDOR_IMG,	RFC1533_VENDOR_IMG+1,	RFC1533_VENDOR_IMG+2,	RFC1533_VENDOR_IMG+3,	RFC1533_VENDOR_IMG+4,	RFC1533_VENDOR_IMG+5,	RFC1533_VENDOR_IMG+6,	RFC1533_VENDOR_IMG+7,	RFC1533_VENDOR_IMG+8,	RFC1533_VENDOR_IMG+9,	RFC1533_VENDOR_IMG+10,	RFC1533_VENDOR_IMG+11,	RFC1533_VENDOR_IMG+12,	RFC1533_VENDOR_IMG+13,	RFC1533_VENDOR_IMG+14,	RFC1533_VENDOR_IMG+15,};#ifdef	REQUIRE_VCI_ETHERBOOTint	vci_etherboot;#endif#endif	/* NO_DHCP_SUPPORT */static int dummy(void *unused __unused){	return (0);}/* Careful.  We need an aligned buffer to avoid problems on machines * that care about alignment.  To trivally align the ethernet data * (the ip hdr and arp requests) we offset the packet by 2 bytes. * leaving the ethernet data 16 byte aligned.  Beyond this * we use memmove but this makes the common cast simple and fast. */static char	packet[ETH_FRAME_LEN + ETH_DATA_ALIGN] __aligned;struct nic	nic ={	{		0,				/* dev.disable */		{			0,			0,			PCI_BUS_TYPE,		},				/* dev.devid */		0,				/* index */		0,				/* type */		PROBE_FIRST,			/* how_pobe */		PROBE_NONE,			/* to_probe */		0,				/* failsafe */		0,				/* type_index */		{},				/* state */	},	(int (*)(struct nic *))dummy,		/* poll */	(void (*)(struct nic *, const char *,		unsigned int, unsigned int,		const char *))dummy,		/* transmit */	0,					/* flags */	&rom,					/* rom_info */	arptable[ARP_CLIENT].node,		/* node_addr */	packet + ETH_DATA_ALIGN,		/* packet */	0,					/* packetlen */	0,					/* priv_data */};#ifdef RARP_NOT_BOOTPstatic int rarp(void);#elsestatic int bootp(void);#endifstatic unsigned short udpchksum(struct iphdr *ip, struct udphdr *udp);int eth_probe(struct dev *dev){	return probe(dev);}int eth_poll(void){	return ((*nic.poll)(&nic));}void eth_transmit(const char *d, unsigned int t, unsigned int s, const void *p){	(*nic.transmit)(&nic, d, t, s, p);	if (t == IP) twiddle();}void eth_disable(void){#ifdef MULTICAST_LEVEL2	int i;	for(i = 0; i < MAX_IGMP; i++) {		leave_group(i);	}#endif	disable(&nic.dev);}/* * Find out what our boot parameters are */int eth_load_configuration(struct dev *dev __unused){	int server_found;	/* Find a server to get BOOTP reply from */#ifdef	RARP_NOT_BOOTP	printf("Searching for server (RARP)...\n");#else#ifndef	NO_DHCP_SUPPORT	printf("Searching for server (DHCP)...\n");#else	printf("Searching for server (BOOTP)...\n");#endif#endif#ifdef	RARP_NOT_BOOTP	server_found = rarp();#else	server_found = bootp();#endif	if (!server_found) {		printf("No Server found\n");		longjmp(restart_etherboot, -1);	}	return 0;}/**************************************************************************LOAD - Try to get booted**************************************************************************/int eth_load(struct dev *dev __unused){	const char	*kernel;	printf("Me: %@, Server: %@",		arptable[ARP_CLIENT].ipaddr.s_addr,		arptable[ARP_SERVER].ipaddr.s_addr);	if (BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr)		printf(", Relay: %@",			BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr);	if (arptable[ARP_GATEWAY].ipaddr.s_addr)		printf(", Gateway %@", arptable[ARP_GATEWAY].ipaddr.s_addr);	putchar('\n');#ifdef	MDEBUG	printf("\n=>>"); getchar();#endif	/* Now use TFTP to load file */#ifdef	DOWNLOAD_PROTO_NFS	rpc_init();#endif#ifdef	DEFAULT_BOOTFILE	kernel = KERNEL_BUF[0] != '\0' ? KERNEL_BUF : DEFAULT_BOOTFILE;#else	kernel = KERNEL_BUF;#endif	loadkernel(kernel); /* We don't return except on error */	printf("Unable to load file.\n");	interruptible_sleep(2);		/* lay off the server for a while */	longjmp(restart_etherboot, -1);}/**************************************************************************DEFAULT_NETMASK - Return default netmask for IP address**************************************************************************/static inline unsigned long default_netmask(void){	int net = ntohl(arptable[ARP_CLIENT].ipaddr.s_addr) >> 24;	if (net <= 127)		return(htonl(0xff000000));	else if (net < 192)		return(htonl(0xffff0000));	else		return(htonl(0xffffff00));}/**************************************************************************IP_TRANSMIT - Send an IP datagram**************************************************************************/static int await_arp(int ival, void *ptr,	unsigned short ptype, struct iphdr *ip __unused, struct udphdr *udp __unused){	struct	arprequest *arpreply;	if (ptype != ARP)		return 0;	if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))		return 0;	arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];	if (arpreply->opcode != htons(ARP_REPLY)) 		return 0;	if (memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) != 0)		return 0;	memcpy(arptable[ival].node, arpreply->shwaddr, ETH_ALEN);	return 1;}int ip_transmit(int len, const void *buf){	unsigned long destip;	struct iphdr *ip;	struct arprequest arpreq;	int arpentry, i;	int retry;	ip = (struct iphdr *)buf;	destip = ip->dest.s_addr;	if (destip == IP_BROADCAST) {		eth_transmit(broadcast, IP, len, buf);#ifdef MULTICAST_LEVEL1 	} else if ((destip & htonl(MULTICAST_MASK)) == htonl(MULTICAST_NETWORK)) {		unsigned char multicast[6];		unsigned long hdestip;		hdestip = ntohl(destip);		multicast[0] = 0x01;		multicast[1] = 0x00;		multicast[2] = 0x5e;		multicast[3] = (hdestip >> 16) & 0x7;		multicast[4] = (hdestip >> 8) & 0xff;		multicast[5] = hdestip & 0xff;		eth_transmit(multicast, IP, len, buf);#endif	} else {		if (((destip & netmask) !=			(arptable[ARP_CLIENT].ipaddr.s_addr & netmask)) &&			arptable[ARP_GATEWAY].ipaddr.s_addr)				destip = arptable[ARP_GATEWAY].ipaddr.s_addr;		for(arpentry = 0; arpentry<MAX_ARP; arpentry++)			if (arptable[arpentry].ipaddr.s_addr == destip) break;		if (arpentry == MAX_ARP) {			printf("%@ is not in my arp table!\n", destip);			return(0);		}		for (i = 0; i < ETH_ALEN; i++)			if (arptable[arpentry].node[i])				break;		if (i == ETH_ALEN) {	/* Need to do arp request */			arpreq.hwtype = htons(1);			arpreq.protocol = htons(IP);			arpreq.hwlen = ETH_ALEN;			arpreq.protolen = 4;			arpreq.opcode = htons(ARP_REQUEST);			memcpy(arpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);			memcpy(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));			memset(arpreq.thwaddr, 0, ETH_ALEN);			memcpy(arpreq.tipaddr, &destip, sizeof(in_addr));			for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) {				long timeout;				eth_transmit(broadcast, ARP, sizeof(arpreq),					&arpreq);				timeout = rfc2131_sleep_interval(TIMEOUT, retry);				if (await_reply(await_arp, arpentry,					arpreq.tipaddr, timeout)) goto xmit;			}			return(0);		}xmit:		eth_transmit(arptable[arpentry].node, IP, len, buf);	}	return 1;}void build_ip_hdr(unsigned long destip, int ttl, int protocol, int option_len,	int len, const void *buf){	struct iphdr *ip;	ip = (struct iphdr *)buf;	ip->verhdrlen = 0x45;	ip->verhdrlen += (option_len/4);	ip->service = 0;	ip->len = htons(len);	ip->ident = 0;	ip->frags = 0; /* Should we set don't fragment? */	ip->ttl = ttl;	ip->protocol = protocol;	ip->chksum = 0;	ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;	ip->dest.s_addr = destip;	ip->chksum = ipchksum(buf, sizeof(struct iphdr) + option_len);}void build_udp_hdr(unsigned long destip, 	unsigned int srcsock, unsigned int destsock, int ttl,	int len, const void *buf){	struct iphdr *ip;	struct udphdr *udp;	ip = (struct iphdr *)buf;	build_ip_hdr(destip, ttl, IP_UDP, 0, len, buf);	udp = (struct udphdr *)((char *)buf + sizeof(struct iphdr));	udp->src = htons(srcsock);	udp->dest = htons(destsock);	udp->len = htons(len - sizeof(struct iphdr));	udp->chksum = 0;	if ((udp->chksum = udpchksum(ip, udp)) == 0)		udp->chksum = 0xffff;}/**************************************************************************UDP_TRANSMIT - Send an UDP datagram**************************************************************************/int udp_transmit(unsigned long destip, unsigned int srcsock,	unsigned int destsock, int len, const void *buf){	build_udp_hdr(destip, srcsock, destsock, 60, len, buf);	return ip_transmit(len, buf);}/**************************************************************************QDRAIN - clear the nic's receive queue**************************************************************************/static int await_qdrain(int ival __unused, void *ptr __unused,	unsigned short ptype __unused, 	struct iphdr *ip __unused, struct udphdr *udp __unused){	return 0;}

⌨️ 快捷键说明

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