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

📄 nic.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 3 页
字号:
void rx_qdrain(void){	/* Clear out the Rx queue first.  It contains nothing of interest,	 * except possibly ARP requests from the DHCP/TFTP server.  We use	 * polling throughout Etherboot, so some time may have passed since we	 * last polled the receive queue, which may now be filled with	 * broadcast packets.  This will cause the reply to the packets we are	 * about to send to be lost immediately.  Not very clever.  */	await_reply(await_qdrain, 0, NULL, 0);}#ifdef	DOWNLOAD_PROTO_TFTP/**************************************************************************TFTP - Download extended BOOTP data, or kernel image**************************************************************************/static int await_tftp(int ival, void *ptr __unused,	unsigned short ptype __unused, struct iphdr *ip, struct udphdr *udp){	if (!udp) {		return 0;	}	if (arptable[ARP_CLIENT].ipaddr.s_addr != ip->dest.s_addr)		return 0;	if (ntohs(udp->dest) != ival)		return 0;	return 1;}int tftp(const char *name, int (*fnc)(unsigned char *, unsigned int, unsigned int, int)){	int             retry = 0;	static unsigned short iport = 2000;	unsigned short  oport = 0;	unsigned short  len, block = 0, prevblock = 0;	int		bcounter = 0;	struct tftp_t  *tr;	struct tftpreq_t tp;	int		rc;	int		packetsize = TFTP_DEFAULTSIZE_PACKET;	rx_qdrain();	tp.opcode = htons(TFTP_RRQ);	/* Warning: the following assumes the layout of bootp_t.	   But that's fixed by the IP, UDP and BOOTP specs. */	len = sizeof(tp.ip) + sizeof(tp.udp) + sizeof(tp.opcode) +		sprintf((char *)tp.u.rrq, "%s%coctet%cblksize%c%d",		name, 0, 0, 0, TFTP_MAX_PACKET) + 1;	if (!udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, ++iport,		TFTP_PORT, len, &tp))		return (0);	for (;;)	{		long timeout;#ifdef	CONGESTED		timeout = rfc2131_sleep_interval(block?TFTP_REXMT: TIMEOUT, retry);#else		timeout = rfc2131_sleep_interval(TIMEOUT, retry);#endif		if (!await_reply(await_tftp, iport, NULL, timeout))		{			if (!block && retry++ < MAX_TFTP_RETRIES)			{	/* maybe initial request was lost */				if (!udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr,					++iport, TFTP_PORT, len, &tp))					return (0);				continue;			}#ifdef	CONGESTED			if (block && ((retry += TFTP_REXMT) < TFTP_TIMEOUT))			{	/* we resend our last ack */#ifdef	MDEBUG				printf("<REXMT>\n");#endif				udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr,					iport, oport,					TFTP_MIN_PACKET, &tp);				continue;			}#endif			break;	/* timeout */		}		tr = (struct tftp_t *)&nic.packet[ETH_HLEN];		if (tr->opcode == ntohs(TFTP_ERROR))		{			printf("TFTP error %d (%s)\n",			       ntohs(tr->u.err.errcode),			       tr->u.err.errmsg);			break;		}		if (tr->opcode == ntohs(TFTP_OACK)) {			const char *p = tr->u.oack.data, *e;			if (prevblock)		/* shouldn't happen */				continue;	/* ignore it */			len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 2;			if (len > TFTP_MAX_PACKET)				goto noak;			e = p + len;			while (*p != '\0' && p < e) {				if (!strcasecmp("blksize", p)) {					p += 8;					if ((packetsize = strtoul(p, &p, 10)) <					    TFTP_DEFAULTSIZE_PACKET)						goto noak;					while (p < e && *p) p++;					if (p < e)						p++;				}				else {				noak:					tp.opcode = htons(TFTP_ERROR);					tp.u.err.errcode = 8;/* *	Warning: the following assumes the layout of bootp_t. *	But that's fixed by the IP, UDP and BOOTP specs. */					len = sizeof(tp.ip) + sizeof(tp.udp) + sizeof(tp.opcode) + sizeof(tp.u.err.errcode) +/* *	Normally bad form to omit the format string, but in this case *	the string we are copying from is fixed. sprintf is just being *	used as a strcpy and strlen. */						sprintf((char *)tp.u.err.errmsg,						"RFC1782 error") + 1;					udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr,						     iport, ntohs(tr->udp.src),						     len, &tp);					return (0);				}			}			if (p > e)				goto noak;			block = tp.u.ack.block = 0; /* this ensures, that */						/* the packet does not get */						/* processed as data! */		}		else if (tr->opcode == htons(TFTP_DATA)) {			len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 4;			if (len > packetsize)	/* shouldn't happen */				continue;	/* ignore it */			block = ntohs(tp.u.ack.block = tr->u.data.block); }		else {/* neither TFTP_OACK nor TFTP_DATA */			break;		}		if ((block || bcounter) && (block != (unsigned short)(prevblock+1))) {			/* Block order should be continuous */			tp.u.ack.block = htons(block = prevblock);		}		tp.opcode = htons(TFTP_ACK);		oport = ntohs(tr->udp.src);		udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, iport,			oport, TFTP_MIN_PACKET, &tp);	/* ack */		if ((unsigned short)(block-prevblock) != 1) {			/* Retransmission or OACK, don't process via callback			 * and don't change the value of prevblock.  */			continue;		}		prevblock = block;		retry = 0;	/* It's the right place to zero the timer? */		if ((rc = fnc(tr->u.data.download,			      ++bcounter, len, len < packetsize)) <= 0)			return(rc);		if (len < packetsize) {	/* End of data --- fnc should not have returned */			printf("tftp download complete, but\n");			return (1);		}	}	return (0);}#endif	/* DOWNLOAD_PROTO_TFTP */#ifdef	RARP_NOT_BOOTP/**************************************************************************RARP - Get my IP address and load information**************************************************************************/static int await_rarp(int ival, void *ptr,	unsigned short ptype, struct iphdr *ip, struct udphdr *udp){	struct arprequest *arpreply;	if (ptype != RARP)		return 0;	if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))		return 0;	arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];	if (arpreply->opcode != htons(RARP_REPLY))		return 0;	if ((arpreply->opcode == htons(RARP_REPLY)) &&		(memcmp(arpreply->thwaddr, ptr, ETH_ALEN) == 0)) {		memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETH_ALEN);		memcpy(&arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr));		memcpy(&arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr));		return 1;	}	return 0;}static int rarp(void){	int retry;	/* arp and rarp requests share the same packet structure. */	struct arprequest rarpreq;	memset(&rarpreq, 0, sizeof(rarpreq));	rarpreq.hwtype = htons(1);	rarpreq.protocol = htons(IP);	rarpreq.hwlen = ETH_ALEN;	rarpreq.protolen = 4;	rarpreq.opcode = htons(RARP_REQUEST);	memcpy(&rarpreq.shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);	/* sipaddr is already zeroed out */	memcpy(&rarpreq.thwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);	/* tipaddr is already zeroed out */	for (retry = 0; retry < MAX_ARP_RETRIES; ++retry) {		long timeout;		eth_transmit(broadcast, RARP, sizeof(rarpreq), &rarpreq);		timeout = rfc2131_sleep_interval(TIMEOUT, retry);		if (await_reply(await_rarp, 0, rarpreq.shwaddr, timeout))			break;	}	if (retry < MAX_ARP_RETRIES) {		(void)sprintf(KERNEL_BUF, DEFAULT_KERNELPATH, arptable[ARP_CLIENT].ipaddr);		return (1);	}	return (0);}#else/**************************************************************************BOOTP - Get my IP address and load information**************************************************************************/static int await_bootp(int ival __unused, void *ptr __unused,	unsigned short ptype __unused, struct iphdr *ip __unused, 	struct udphdr *udp){	struct	bootp_t *bootpreply;	if (!udp) {		return 0;	}	bootpreply = (struct bootp_t *)&nic.packet[ETH_HLEN + 		sizeof(struct iphdr) + sizeof(struct udphdr)];	if (nic.packetlen < ETH_HLEN + sizeof(struct iphdr) + 		sizeof(struct udphdr) + #ifdef NO_DHCP_SUPPORT		sizeof(struct bootp_t)#else		sizeof(struct bootp_t) - DHCP_OPT_LEN#endif	/* NO_DHCP_SUPPORT */		) {		return 0;	}	if (udp->dest != htons(BOOTP_CLIENT))		return 0;	if (bootpreply->bp_op != BOOTP_REPLY)		return 0;	if (bootpreply->bp_xid != xid)		return 0;	if (memcmp(&bootpreply->bp_siaddr, &zeroIP, sizeof(in_addr)) == 0)		return 0;#ifndef	DEFAULT_BOOTFILE	if (bootpreply->bp_file[0] == '\0') {		printf("F?");	/* No filename in offer */		return 0;	}#endif	if ((memcmp(broadcast, bootpreply->bp_hwaddr, ETH_ALEN) != 0) &&		(memcmp(arptable[ARP_CLIENT].node, bootpreply->bp_hwaddr, ETH_ALEN) != 0)) {		return 0;	}	arptable[ARP_CLIENT].ipaddr.s_addr = bootpreply->bp_yiaddr.s_addr;#ifndef	NO_DHCP_SUPPORT	dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;#endif	/* NO_DHCP_SUPPORT */	netmask = default_netmask();	arptable[ARP_SERVER].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;	memset(arptable[ARP_SERVER].node, 0, ETH_ALEN);  /* Kill arp */	arptable[ARP_GATEWAY].ipaddr.s_addr = bootpreply->bp_giaddr.s_addr;	memset(arptable[ARP_GATEWAY].node, 0, ETH_ALEN);  /* Kill arp */	/* bootpreply->bp_file will be copied to KERNEL_BUF in the memcpy */	memcpy((char *)BOOTP_DATA_ADDR, (char *)bootpreply, sizeof(struct bootpd_t));	decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend, 0,#ifdef	NO_DHCP_SUPPORT		BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN, #else		DHCP_OPT_LEN + MAX_BOOTP_EXTLEN, #endif	/* NO_DHCP_SUPPORT */		1);#ifdef	REQUIRE_VCI_ETHERBOOT	if (!vci_etherboot)		return (0);#endif	return(1);}static int bootp(void){	int retry;#ifndef	NO_DHCP_SUPPORT	int reqretry;#endif	/* NO_DHCP_SUPPORT */	struct bootpip_t ip;	unsigned long  starttime;	unsigned char *bp_vend;#ifndef	NO_DHCP_SUPPORT	dhcp_machine_info[4] = nic.dev.devid.bus_type;	dhcp_machine_info[5] = nic.dev.devid.vendor_id & 0xff;	dhcp_machine_info[6] = ((nic.dev.devid.vendor_id) >> 8) & 0xff;	dhcp_machine_info[7] = nic.dev.devid.device_id & 0xff;	dhcp_machine_info[8] = ((nic.dev.devid.device_id) >> 8) & 0xff;#endif	/* NO_DHCP_SUPPORT */	memset(&ip, 0, sizeof(struct bootpip_t));	ip.bp.bp_op = BOOTP_REQUEST;	ip.bp.bp_htype = 1;	ip.bp.bp_hlen = ETH_ALEN;	starttime = currticks();	/* Use lower 32 bits of node address, more likely to be	   distinct than the time since booting */	memcpy(&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid));	ip.bp.bp_xid = xid += htonl(starttime);	memcpy(ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);#ifdef	NO_DHCP_SUPPORT	memcpy(ip.bp.bp_vend, rfc1533_cookie, 5); /* request RFC-style options */#else	memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */	memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover);	/* Append machine_info to end, in encapsulated option */	bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcpdiscover;	memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);	bp_vend += DHCP_MACHINE_INFO_SIZE;	*bp_vend++ = RFC1533_END;#endif	/* NO_DHCP_SUPPORT */	for (retry = 0; retry < MAX_BOOTP_RETRIES; ) {		long timeout;		rx_qdrain();		udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,			sizeof(struct bootpip_t), &ip);		timeout = rfc2131_sleep_interval(TIMEOUT, retry++);#ifdef	NO_DHCP_SUPPORT		if (await_reply(await_bootp, 0, NULL, timeout))			return(1);#else		if (await_reply(await_bootp, 0, NULL, timeout)) {			/* If not a DHCPOFFER then must be just a BOOTP reply,			   be backward compatible with BOOTP then */			if (dhcp_reply != DHCPOFFER)				return(1);			dhcp_reply = 0;			memcpy(ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);			memcpy(ip.bp.bp_vend + sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest);			/* Beware: the magic numbers 9 and 15 depend on			   the layout of dhcprequest */			memcpy(&ip.bp.bp_vend[9], &dhcp_server, sizeof(in_addr));			memcpy(&ip.bp.bp_vend[15], &dhcp_addr, sizeof(in_addr));			bp_vend = ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcprequest;			/* Append machine_info to end, in encapsulated option */			memcpy(bp_vend, dhcp_machine_info, DHCP_MACHINE_INFO_SIZE);			bp_vend += DHCP_MACHINE_INFO_SIZE;			*bp_vend++ = RFC1533_END;			for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES; ) {				udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,					sizeof(struct bootpip_t), &ip);				dhcp_reply=0;				timeout = rfc2131_sleep_interval(TIMEOUT, reqretry++);				if (await_reply(await_bootp, 0, NULL, timeout))					if (dhcp_reply == DHCPACK)						return(1);			}		}#endif	/* NO_DHCP_SUPPORT */		ip.bp.bp_secs = htons((currticks()-starttime)/TICKS_PER_SEC);	}	return(0);}#endif	/* RARP_NOT_BOOTP */static uint16_t udpchksum(struct iphdr *ip, struct udphdr *udp){	struct udp_pseudo_hdr pseudo;	uint16_t checksum;	/* Compute the pseudo header */	pseudo.src.s_addr  = ip->src.s_addr;	pseudo.dest.s_addr = ip->dest.s_addr;	pseudo.unused      = 0;	pseudo.protocol    = IP_UDP;	pseudo.len         = udp->len;	/* Sum the pseudo header */	checksum = ipchksum(&pseudo, 12);	/* Sum the rest of the udp packet */	checksum = add_ipchksums(12, checksum, ipchksum(udp, ntohs(udp->len)));	return checksum;}#ifdef MULTICAST_LEVEL2static void send_igmp_reports(unsigned long now){	int i;	for(i = 0; i < MAX_IGMP; i++) {		if (igmptable[i].time && (now >= igmptable[i].time)) {			struct igmp_ip_t igmp;			igmp.router_alert[0] = 0x94;			igmp.router_alert[1] = 0x04;			igmp.router_alert[2] = 0;			igmp.router_alert[3] = 0;			build_ip_hdr(igmptable[i].group.s_addr, 				1, IP_IGMP, sizeof(igmp.router_alert), sizeof(igmp), &igmp);			igmp.igmp.type = IGMPv2_REPORT;			if (last_igmpv1 && 				(now < last_igmpv1 + IGMPv1_ROUTER_PRESENT_TIMEOUT)) {				igmp.igmp.type = IGMPv1_REPORT;			}			igmp.igmp.response_time = 0;			igmp.igmp.chksum = 0;			igmp.igmp.group.s_addr = igmptable[i].group.s_addr;			igmp.igmp.chksum = ipchksum(&igmp.igmp, sizeof(igmp.igmp));			ip_transmit(sizeof(igmp), &igmp);#ifdef	MDEBUG			printf("Sent IGMP report to: %@\n", igmp.igmp.group.s_addr);

⌨️ 快捷键说明

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