📄 main.c
字号:
{ grub_memmove ((char *) arptable[ival].node, arpreply->shwaddr, ETH_ALEN); return 1; } grub_memmove ((char *) &tmp, arpreply->tipaddr, sizeof (in_addr)); if (arpreply->opcode == htons (ARP_REQUEST) && tmp == arptable[ARP_CLIENT].ipaddr.s_addr) { arpreply->opcode = htons (ARP_REPLY); grub_memmove (arpreply->tipaddr, arpreply->sipaddr, sizeof (in_addr)); grub_memmove (arpreply->thwaddr, (char *) arpreply->shwaddr, ETH_ALEN); grub_memmove (arpreply->sipaddr, (char *) &arptable[ARP_CLIENT].ipaddr, sizeof (in_addr)); grub_memmove (arpreply->shwaddr, arptable[ARP_CLIENT].node, ETH_ALEN); eth_transmit (arpreply->thwaddr, ARP, sizeof (struct arprequest), arpreply);#ifdef MDEBUG grub_memmove (&tmp, arpreply->tipaddr, sizeof (in_addr)); etherboot_printf ("Sent ARP reply to: %@\n", tmp);#endif /* MDEBUG */ } continue; } if (type == AWAIT_QDRAIN) continue; /* Check for RARP - No IP hdr. */ if (type == AWAIT_RARP && nic.packetlen >= ETH_HLEN + sizeof (struct arprequest) && ptype == RARP) { arpreply = (struct arprequest *) &nic.packet[ETH_HLEN]; if (arpreply->opcode == htons (RARP_REPLY) && ! grub_memcmp (arpreply->thwaddr, ptr, ETH_ALEN)) { grub_memmove ((char *) arptable[ARP_SERVER].node, arpreply->shwaddr, ETH_ALEN); grub_memmove ((char *) &arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof (in_addr)); grub_memmove ((char *) &arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof (in_addr)); return 1; } continue; } /* Anything else has IP header. */ if (nic.packetlen < protohdrlen || ptype != IP) continue; ip = (struct iphdr *) &nic.packet[ETH_HLEN]; if (ip->verhdrlen != 0x45 || ipchksum ((unsigned short *) ip, sizeof (struct iphdr)) || ip->protocol != IP_UDP) continue; /* - Till Straumann <Till.Straumann@TU-Berlin.de> added udp checksum (safer on a wireless link) added fragmentation check: I had a corrupted image in memory due to fragmented TFTP packets - took me 3 days to find the cause for this :-( */ /* If More Fragments bit and Fragment Offset field are non-zero then packet is fragmented */ if (ip->frags & htons(0x3FFF)) { grub_printf ("ALERT: got a fragmented packet - reconfigure your server\n"); continue; } udp = (struct udphdr *) &nic.packet[(ETH_HLEN + sizeof (struct iphdr))]; if (udp->chksum && udpchksum (ip)) { grub_printf ("UDP checksum error\n"); continue; } /* BOOTP ? */ bootpreply = (struct bootp_t *) &nic.packet[(ETH_HLEN + sizeof (struct iphdr) + sizeof (struct udphdr))]; if (type == AWAIT_BOOTP#ifdef NO_DHCP_SUPPORT && (nic.packetlen >= (ETH_HLEN + sizeof (struct bootp_t) - BOOTP_VENDOR_LEN))#else && (nic.packetlen >= (ETH_HLEN + sizeof (struct bootp_t) - DHCP_OPT_LEN))#endif /* ! NO_DHCP_SUPPORT */ && udp->dest == htons (BOOTP_CLIENT) && bootpreply->bp_op == BOOTP_REPLY && bootpreply->bp_xid == xid && (! grub_memcmp (broadcast, bootpreply->bp_hwaddr, ETH_ALEN) || ! grub_memcmp (arptable[ARP_CLIENT].node, bootpreply->bp_hwaddr, ETH_ALEN))) {#ifdef DEBUG grub_printf ("BOOTP packet was received.\n");#endif arptable[ARP_CLIENT].ipaddr.s_addr = bootpreply->bp_yiaddr.s_addr;#ifndef NO_DHCP_SUPPORT dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;#ifdef DEBUG etherboot_printf ("dhcp_addr = %@\n", dhcp_addr.s_addr);#endif#endif /* ! NO_DHCP_SUPPORT */ netmask = default_netmask (); arptable[ARP_SERVER].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr; /* Kill arp. */ grub_memset (arptable[ARP_SERVER].node, 0, ETH_ALEN); arptable[ARP_GATEWAY].ipaddr.s_addr = bootpreply->bp_giaddr.s_addr; /* Kill arp. */ grub_memset (arptable[ARP_GATEWAY].node, 0, ETH_ALEN); grub_memmove ((char *) BOOTP_DATA_ADDR, (char *) bootpreply, sizeof (struct bootpd_t));#ifdef NO_DHCP_SUPPORT decode_rfc1533 (BOOTP_DATA_ADDR->bootp_reply.bp_vend, 0, BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN, 1);#else decode_rfc1533 (BOOTP_DATA_ADDR->bootp_reply.bp_vend, 0, DHCP_OPT_LEN + MAX_BOOTP_EXTLEN, 1);#endif /* ! NO_DHCP_SUPPORT */ return 1; } /* TFTP ? */ if (type == AWAIT_TFTP && ntohs (udp->dest) == ival) return 1; } else { /* Check for abort key only if the Rx queue is empty - * as long as we have something to process, don't * assume that something failed. It is unlikely that * we have no processing time left between packets. */ if (checkkey () != -1 && ASCII_CHAR (getkey ()) == CTRL_C) { ip_abort = 1; return 0; } /* Do the timeout after at least a full queue walk. */ if ((timeout == 0) || (currticks() > time)) { break; } } } return 0;}/**************************************************************************DECODE_RFC1533 - Decodes RFC1533 header**************************************************************************/intdecode_rfc1533 (unsigned char *p, int block, int len, int eof){ static unsigned char *extdata = NULL, *extend = NULL; unsigned char *extpath = NULL; unsigned char *endp; if (block == 0) { end_of_rfc1533 = NULL; vendorext_isvalid = 0; if (grub_memcmp (p, rfc1533_cookie, 4)) /* no RFC 1533 header found */ return 0; p += 4; endp = p + len; } else { if (block == 1) { if (grub_memcmp (p, rfc1533_cookie, 4)) /* no RFC 1533 header found */ return 0; p += 4; len -= 4; } if (extend + len <= ((unsigned char *) &(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN]))) { grub_memmove (extend, p, len); extend += len; } else { grub_printf ("Overflow in vendor data buffer! Aborting...\n"); *extdata = RFC1533_END; return 0; } p = extdata; endp = extend; } if (! eof) return -1; while (p < endp) { unsigned char c = *p; if (c == RFC1533_PAD) { p++; continue; } else if (c == RFC1533_END) { end_of_rfc1533 = endp = p; continue; } else if (c == RFC1533_NETMASK) { grub_memmove ((char *) &netmask, p + 2, sizeof (in_addr)); } else if (c == RFC1533_GATEWAY) { /* This is a little simplistic, but it will usually be sufficient. Take only the first entry. */ if (TAG_LEN (p) >= sizeof (in_addr)) grub_memmove ((char *) &arptable[ARP_GATEWAY].ipaddr, p + 2, sizeof (in_addr)); } else if (c == RFC1533_EXTENSIONPATH) extpath = p;#ifndef NO_DHCP_SUPPORT else if (c == RFC2132_MSG_TYPE) { dhcp_reply = *(p + 2); } else if (c == RFC2132_SRV_ID) { grub_memmove ((char *) &dhcp_server, p + 2, sizeof (in_addr));#ifdef DEBUG etherboot_printf ("dhcp_server = %@\n", dhcp_server.s_addr);#endif }#endif /* ! NO_DHCP_SUPPORT */ else if (c == RFC1533_VENDOR_MAGIC && TAG_LEN(p) >= 6 && ! grub_memcmp (p + 2, vendorext_magic, 4) && p[6] == RFC1533_VENDOR_MAJOR) vendorext_isvalid++; /* GRUB now handles its own tag. Get the name of a configuration file from the network. Cool... */ else if (c == RFC1533_VENDOR_CONFIGFILE) { int l = TAG_LEN (p); /* Eliminate the trailing NULs according to RFC 2132. */ while (*(p + 2 + l - 1) == '\000' && l > 0) l--; /* XXX: Should check if LEN is less than the maximum length of CONFIG_FILE. This kind of robustness will be a goal in GRUB 1.0. */ grub_memmove (config_file, p + 2, l); config_file[l] = 0; } p += TAG_LEN (p) + 2; } extdata = extend = endp; /* Perhaps we can eliminate this because we doesn't require so much information, but I leave this alone. */ if (block == 0 && extpath != NULL) { char fname[64]; int fnamelen = TAG_LEN (extpath); while (*(extpath + 2 + fnamelen - 1) == '\000' && fnamelen > 0) fnamelen--; if (fnamelen + 1 > sizeof (fname)) { grub_printf ("Too long file name for Extensions Path\n"); return 0; } else if (! fnamelen) { grub_printf ("Empty file name for Extensions Path\n"); return 0; } grub_memmove (fname, extpath + 2, fnamelen); fname[fnamelen] = '\000'; grub_printf ("Loading BOOTP-extension file: %s\n", fname); tftp (fname, decode_rfc1533); } /* Proceed with next block. */ return -1;}/**************************************************************************IPCHKSUM - Checksum IP Header**************************************************************************/static unsigned short ipchksum (unsigned short *ip, int len){ unsigned long sum = 0; len >>= 1; while (len--) { sum += *(ip++); if (sum > 0xFFFF) sum -= 0xFFFF; } return (~sum) & 0x0000FFFF;}#define TWO_SECOND_DIVISOR (2147483647l/TICKS_PER_SEC)/**************************************************************************RFC2131_SLEEP_INTERVAL - sleep for expotentially longer times**************************************************************************/longrfc2131_sleep_interval (int base, int exp){ static long seed = 0; long q; unsigned long tmo; #ifdef BACKOFF_LIMIT if (exp > BACKOFF_LIMIT) exp = BACKOFF_LIMIT;#endif if (!seed) /* Initialize linear congruential generator */ seed = (currticks () + *((long *) &arptable[ARP_CLIENT].node) + ((short *) arptable[ARP_CLIENT].node)[2]); /* simplified version of the LCG given in Bruce Schneier's "Applied Cryptography" */ q = seed / 53668; if ((seed = 40014 * (seed - 53668 * q) - 12211 *q ) < 0) seed += 2147483563L; tmo = (base << exp) + (TICKS_PER_SEC - (seed / TWO_SECOND_DIVISOR)); return tmo;}/**************************************************************************CLEANUP - shut down networking**************************************************************************/voidcleanup_net (void){ if (network_ready) { /* Stop receiving packets. */ eth_disable (); network_ready = 0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -