📄 main.c
字号:
#endif bp.bp_secs = htons((currticks()-starttime)/20); } return(0);}#endif /* RARP_NOT_BOOTP *//**************************************************************************AWAIT_REPLY - Wait until we get a response for our request**************************************************************************/int await_reply(int type, int ival, void *ptr, int timeout){ unsigned long time; struct iphdr *ip; struct udphdr *udp; struct arprequest *arpreply; struct bootp_t *bootpreply; struct rpc_t *rpc; unsigned short ptype; unsigned int protohdrlen = ETHER_HDR_SIZE + sizeof(struct iphdr) + sizeof(struct udphdr); time = timeout + currticks(); /* The timeout check is done below. The timeout is only checked if * there is no packet in the Rx queue. This assumes that eth_poll() * needs a negligible amount of time. */ for (;;) { if (eth_poll()) { /* We have something! */ /* Check for ARP - No IP hdr */ if (nic.packetlen >= ETHER_HDR_SIZE) { ptype = ((unsigned short) nic.packet[12]) << 8 | ((unsigned short) nic.packet[13]); } else continue; /* what else could we do with it? */ if ((nic.packetlen >= ETHER_HDR_SIZE + sizeof(struct arprequest)) && (ptype == ARP) ) { unsigned long tmp; arpreply = (struct arprequest *) &nic.packet[ETHER_HDR_SIZE]; if ((arpreply->opcode == ntohs(ARP_REPLY)) && !memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) && (type == AWAIT_ARP)) { memcpy(arptable[ival].node, arpreply->shwaddr, ETHER_ADDR_SIZE); return(1); } memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr)); if ((arpreply->opcode == ntohs(ARP_REQUEST)) && (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) { arpreply->opcode = htons(ARP_REPLY); memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr)); memcpy(arpreply->thwaddr, arpreply->shwaddr, ETHER_ADDR_SIZE); memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr)); memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE); eth_transmit(arpreply->thwaddr, ARP, sizeof(struct arprequest), arpreply);#ifdef MDEBUG memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr)); printf("Sent ARP reply to: %I\n",tmp);#endif MDEBUG } continue; } if (type == AWAIT_QDRAIN) { continue; } /* Check for RARP - No IP hdr */ if ((type == AWAIT_RARP) && (nic.packetlen >= ETHER_HDR_SIZE + sizeof(struct arprequest)) && (ptype == RARP)) { arpreply = (struct arprequest *) &nic.packet[ETHER_HDR_SIZE]; if ((arpreply->opcode == ntohs(RARP_REPLY)) && !memcmp(arpreply->thwaddr, ptr, ETHER_ADDR_SIZE)) { memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETHER_ADDR_SIZE); memcpy(& arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr)); memcpy(& 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[ETHER_HDR_SIZE]; if ((ip->verhdrlen != 0x45) || ipchksum((unsigned short *)ip, sizeof(struct iphdr)) || (ip->protocol != IP_UDP)) continue; udp = (struct udphdr *)&nic.packet[ETHER_HDR_SIZE + sizeof(struct iphdr)]; /* BOOTP ? */ bootpreply = (struct bootp_t *)&nic.packet[ETHER_HDR_SIZE]; if ((type == AWAIT_BOOTP) && (nic.packetlen >= (ETHER_HDR_SIZE +#ifdef NO_DHCP_SUPPORT sizeof(struct bootp_t))) &&#else sizeof(struct bootp_t))-DHCP_OPT_LEN) &&#endif /* NO_DHCP_SUPPORT */ (ntohs(udp->dest) == BOOTP_CLIENT) && (bootpreply->bp_op == BOOTP_REPLY) && (bootpreply->bp_xid == xid)) { 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, ETHER_ADDR_SIZE); /* Kill arp */ arptable[ARP_GATEWAY].ipaddr.s_addr = bootpreply->bp_giaddr.s_addr; memset(arptable[ARP_GATEWAY].node, 0, ETHER_ADDR_SIZE); /* Kill arp */ if (bootpreply->bp_file[0]) { memcpy(kernel_buf, bootpreply->bp_file, 128); kernel = kernel_buf; } memcpy((char *)BOOTP_DATA_ADDR, (char *)bootpreply, sizeof(struct bootpd_t)); decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend,#ifdef NO_DHCP_SUPPORT 0, BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN, 1);#else 0, DHCP_OPT_LEN + MAX_BOOTP_EXTLEN, 1);#endif /* NO_DHCP_SUPPORT */ return(1); }#ifdef DOWNLOAD_PROTO_TFTP /* TFTP ? */ if ((type == AWAIT_TFTP) && (ntohs(udp->dest) == ival)) return(1);#endif /* DOWNLOAD_PROTO_TFTP */#ifdef DOWNLOAD_PROTO_NFS /* RPC ? */ rpc = (struct rpc_t *)&nic.packet[ETHER_HDR_SIZE]; if ((type == AWAIT_RPC) && (ntohs(udp->dest) == ival) && (*(unsigned long *)ptr == ntohl(rpc->u.reply.id)) && (ntohl(rpc->u.reply.type) == MSG_REPLY)) { return (1); }#endif /* DOWNLOAD_PROTO_NFS */ } 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 (iskey() && (getchar() == ESC))#ifdef EMERGENCYDISKBOOT exit(0);#else longjmp(jmp_bootmenu,1);#endif /* Do the timeout after at least a full queue walk. */ if ((timeout == 0) || (currticks() > time)) { break; } } } return(0);}/**************************************************************************DECODE_RFC1533 - Decodes RFC1533 header**************************************************************************/int decode_rfc1533(p, block, len, eof) register unsigned char *p; int block, len, eof;{ static unsigned char *extdata = NULL, *extend = NULL; unsigned char *extpath = NULL; unsigned char *endp; if (block == 0) {#ifdef IMAGE_MENU memset(imagelist, 0, sizeof(imagelist)); menudefault = useimagemenu = 0; menutmo = -1;#endif#ifdef MOTD memset(motd, 0, sizeof(motd));#endif end_of_rfc1533 = NULL; vendorext_isvalid = 0; if (memcmp(p, rfc1533_cookie, 4)) return(0); /* no RFC 1533 header found */ p += 4; endp = p + len; } else { if (block == 1) { if (memcmp(p, rfc1533_cookie, 4)) return(0); /* no RFC 1533 header found */ p += 4; len -= 4; } if (extend + len <= (unsigned char *)&(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN])) { memcpy(extend, p, len); extend += len; } else { printf("Overflow in vendor data buffer! Aborting...\n"); *extdata = RFC1533_END; return(0); } p = extdata; endp = extend; } if (eof) { 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) {memcpy(&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)) memcpy(&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) { memcpy(&dhcp_server, p+2, sizeof(in_addr)); }#endif /* NO_DHCP_SUPPORT */ else if (c == RFC1533_HOSTNAME) { hostname = p + 2; hostnamelen = *(p + 1); } else if (c == RFC1533_VENDOR_MAGIC#ifndef IMAGE_FREEBSD /* since FreeBSD uses tag 128 for swap definition */ && TAG_LEN(p) >= 6 && !memcmp(p+2,vendorext_magic,4) && p[6] == RFC1533_VENDOR_MAJOR#endif ) vendorext_isvalid++;#ifdef IMAGE_FREEBSD else if (c == RFC1533_VENDOR_HOWTO) { freebsd_howto = ((p[2]*256+p[3])*256+p[4])*256+p[5]; }#endif#ifdef IMAGE_MENU else if (c == RFC1533_VENDOR_MNUOPTS) { parse_menuopts(p+2, TAG_LEN(p)); } else if (c >= RFC1533_VENDOR_IMG && c<RFC1533_VENDOR_IMG+RFC1533_VENDOR_NUMOFIMG){ imagelist[c - RFC1533_VENDOR_IMG] = p; useimagemenu++; }#endif#ifdef MOTD else if (c >= RFC1533_VENDOR_MOTD && c < RFC1533_VENDOR_MOTD + RFC1533_VENDOR_NUMOFMOTD) motd[c - RFC1533_VENDOR_MOTD] = p;#endif else {#if 0 unsigned char *q; printf("Unknown RFC1533-tag "); for(q=p;q<p+2+TAG_LEN(p);q++) printf("%x ",*q); putchar('\n');#endif } p += TAG_LEN(p) + 2; } extdata = extend = endp; if (block == 0 && extpath != NULL) { char fname[64]; memcpy(fname, extpath+2, TAG_LEN(extpath)); fname[(int)TAG_LEN(extpath)] = '\000'; printf("Loading BOOTP-extension file: %s\n",fname); download(fname,decode_rfc1533); } } return(-1); /* proceed with next block */}/**************************************************************************IPCHKSUM - Checksum IP Header**************************************************************************/unsigned short ipchksum(ip, len) register unsigned short *ip; register int len;{ unsigned long sum = 0; len >>= 1; while (len--) { sum += *(ip++); if (sum > 0xFFFF) sum -= 0xFFFF; } return((~sum) & 0x0000FFFF);}/**************************************************************************RFC951_SLEEP - sleep for expotentially longer times**************************************************************************/void rfc951_sleep(exp) 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 Scheier's "Applied Cryptography" */ q = seed/53668; if ((seed = 40014*(seed-53668*q) - 12211*q) < 0) seed += 2147483563l; /* compute mask */ for (tmo = 63; tmo <= 60*TICKS_PER_SEC && --exp > 0; tmo = 2*tmo+1); /* sleep */ printf("<sleep>\n"); for (tmo = (tmo&seed)+currticks(); currticks() < tmo; ) if (iskey() && (getchar() == ESC)) longjmp(jmp_bootmenu,1); return;}/**************************************************************************CLEANUP_NET - shut down networking**************************************************************************/void cleanup_net(void){#ifdef DOWNLOAD_PROTO_NFS nfs_umountall(ARP_SERVER);#endif eth_disable(); eth_reset();}/**************************************************************************CLEANUP - shut down etherboot so that the OS may be called right away**************************************************************************/void cleanup(void){#if defined(ANSIESC) && defined(CONSOLE_CRT) ansi_reset();#endif}/* * Local variables: * c-basic-offset: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -