📄 main.c
字号:
if (destip == IP_BROADCAST) { eth_transmit(broadcast, IP, len, buf); } 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("%I is not in my arp table!\n", destip); return(0); } for (i = 0; i<ETHER_ADDR_SIZE; i++) if (arptable[arpentry].node[i]) break; if (i == ETHER_ADDR_SIZE) { /* Need to do arp request */ arpreq.hwtype = htons(1); arpreq.protocol = htons(IP); arpreq.hwlen = ETHER_ADDR_SIZE; arpreq.protolen = 4; arpreq.opcode = htons(ARP_REQUEST); memcpy(arpreq.shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE); memcpy(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr)); memset(arpreq.thwaddr, 0, ETHER_ADDR_SIZE); memcpy(arpreq.tipaddr, &destip, sizeof(in_addr)); for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) { eth_transmit(broadcast, ARP, sizeof(arpreq), &arpreq); if (await_reply(AWAIT_ARP, arpentry, arpreq.tipaddr, TIMEOUT)) goto xmit; rfc951_sleep(retry); /* We have slept for a while - the packet may * have arrived by now. If not, we have at * least some room in the Rx buffer for the * next reply. */ if (await_reply(AWAIT_ARP, arpentry, arpreq.tipaddr, 0)) goto xmit; } return(0); }xmit: eth_transmit(arptable[arpentry].node, IP, len, buf); } return(1);}/**************************************************************************DOWNLOADKERNEL - Try to load file**************************************************************************/int downloadkernel(data, block, len, eof) unsigned char *data; int block, len, eof;{#ifdef SIZEINDICATOR static int rlen = 0; if (!(block % 4) || eof) { int size; size = ((block-1) * rlen + len) / 1024; putchar('\b'); putchar('\b'); putchar('\b'); putchar('\b'); putchar('0' + (size/1000)%10); putchar('0' + (size/100)%10); putchar('0' + (size/10)%10); putchar('0' + (size/1)%10); }#endif if (block == 1) {#ifdef SIZEINDICATOR rlen=len;#endif if (!eof && (#ifdef TAGGED_IMAGE *((unsigned long *)data) == 0x1B031336L ||#endif#ifdef ELF_IMAGE *((unsigned long *)data) == 0x464C457FL ||#endif#ifdef AOUT_IMAGE *((unsigned short *)data) == 0x010BL ||#endif ((unsigned short *)data)[255] == 0xAA55)) { ; } else if (eof) { memcpy(config_buffer, data, len); config_buffer[len] = 0; return (1); /* done */ } else { printf("error: not a tagged image\n"); return(0); /* error */ } } if (len != 0) { if (!os_download(block, data, len)) return(0); /* error */ } if (eof) { os_download(block+1, data, 0); /* does not return */ return(0); /* error */ } return(-1); /* there is more data */}#ifdef DOWNLOAD_PROTO_TFTP/**************************************************************************TFTP - Download extended BOOTP data, or kernel image**************************************************************************/int tftp(const char *name, int (*fnc)(unsigned char *, int, int, int)){ int retry = 0; static unsigned short iport = 2000; unsigned short oport; unsigned short len, block = 0, prevblock = 0; int bcounter = 0; struct tftp_t *tr; struct tftp_t tp; int rc; int packetsize = TFTP_DEFAULTSIZE_PACKET; /* 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); tp.opcode = htons(TFTP_RRQ); len = (sprintf((char *)tp.u.rrq, "%s%coctet%cblksize%c%d", name, 0, 0, 0, TFTP_MAX_PACKET) - ((char *)&tp)) + 1; if (!udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, ++iport, TFTP_PORT, len, &tp)) return (0); for (;;) {#ifdef CONGESTED if (!await_reply(AWAIT_TFTP, iport, NULL, (block ? TFTP_REXMT : TIMEOUT)))#else if (!await_reply(AWAIT_TFTP, iport, NULL, TIMEOUT))#endif { if (!block && retry++ < MAX_TFTP_RETRIES) { /* maybe initial request was lost */ rfc951_sleep(retry); 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[ETHER_HDR_SIZE]; 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)) { 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 != '\000' && p < e) { if (!strcasecmp("blksize", p)) { p += 8; if ((packetsize = getdec(&p)) < 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; len = (sprintf((char *)tp.u.err.errmsg, "RFC1782 error") - ((char *)&tp)) + 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 == ntohs(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 != 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 */ return (1); } return (0);}#endif /* DOWNLOAD_PROTO_TFTP */#ifdef RARP_NOT_BOOTP/**************************************************************************RARP - Get my IP address and load information**************************************************************************/int rarp(){ 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 = ETHER_ADDR_SIZE; rarpreq.protolen = 4; rarpreq.opcode = htons(RARP_REQUEST); memcpy(&rarpreq.shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE); /* sipaddr is already zeroed out */ memcpy(&rarpreq.thwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE); /* tipaddr is already zeroed out */ for (retry = 0; retry < MAX_ARP_RETRIES; rfc951_sleep(++retry)) { eth_transmit(broadcast, RARP, sizeof(rarpreq), &rarpreq); if (await_reply(AWAIT_RARP, 0, rarpreq.shwaddr, TIMEOUT)) break; } if (retry < MAX_ARP_RETRIES) { sprintf(kernel = kernel_buf, "/tftpboot/kernel.%I", arptable[ARP_CLIENT].ipaddr); return (1); } return (0);}#else/**************************************************************************BOOTP - Get my IP address and load information**************************************************************************/int bootp(){ int retry;#ifndef NO_DHCP_SUPPORT int retry1;#endif /* NO_DHCP_SUPPORT */ struct bootp_t bp; unsigned long starttime;#ifdef T509HACK int flag; flag = 1;#endif memset(&bp, 0, sizeof(struct bootp_t)); bp.bp_op = BOOTP_REQUEST; bp.bp_htype = 1; bp.bp_hlen = ETHER_ADDR_SIZE; bp.bp_xid = xid = starttime = currticks(); memcpy(bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE);#ifdef NO_DHCP_SUPPORT memcpy(bp.bp_vend, rfc1533_cookie, 5); /* request RFC-style options */#else memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */ memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover); memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcpdiscover, rfc1533_end, sizeof rfc1533_end);#endif /* NO_DHCP_SUPPORT */ for (retry = 0; retry < MAX_BOOTP_RETRIES; ) { /* 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); udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER, sizeof(struct bootp_t), &bp);#ifdef T509HACK if (flag) { flag--; } else { if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT)) return(1); rfc951_sleep(++retry); }#else#ifdef NO_DHCP_SUPPORT if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT))#else if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT)){ if (dhcp_reply==DHCPOFFER){ dhcp_reply=0; memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest); memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcprequest, rfc1533_end, sizeof rfc1533_end); memcpy(bp.bp_vend+9, &dhcp_server, sizeof(in_addr)); memcpy(bp.bp_vend+15, &dhcp_addr, sizeof(in_addr)); for (retry1 = 0; retry1 < MAX_BOOTP_RETRIES;) { udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER, sizeof(struct bootp_t), &bp); dhcp_reply=0; if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT)) if (dhcp_reply==DHCPACK) return(1); rfc951_sleep(++retry1); } } else#endif /* NO_DHCP_SUPPORT */ return(1);#ifndef NO_DHCP_SUPPORT } rfc951_sleep(++retry);#endif /* NO_DHCP_SUPPORT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -