📄 main.c
字号:
default_netmask(){ int net = arptable[ARP_CLIENT].ipaddr >> 24; if (net <= 127) netmask = htonl(0xff000000); else if (net < 192) netmask = htonl(0xffff0000); else netmask = htonl(0xffffff00);}/**************************************************************************UDP_TRANSMIT - Send a UDP datagram**************************************************************************/udp_transmit(destip, srcsock, destsock, len, buf) unsigned long destip; unsigned short srcsock, destsock; int len; char *buf;{ struct iphdr *ip; struct udphdr *udp; struct arprequest arpreq; int arpentry, i; unsigned long time; int retry = MAX_ARP_RETRIES; ip = (struct iphdr *)buf; udp = (struct udphdr *)(buf + sizeof(struct iphdr)); ip->verhdrlen = 0x45; ip->service = 0; ip->len = htons(len); ip->ident = 0; ip->frags = 0; ip->ttl = 60; ip->protocol = IP_UDP; ip->chksum = 0; convert_ipaddr(ip->src, &arptable[ARP_CLIENT].ipaddr); convert_ipaddr(ip->dest, &destip); ip->chksum = ipchksum(buf, sizeof(struct iphdr)); udp->src = htons(srcsock); udp->dest = htons(destsock); udp->len = htons(len - sizeof(struct iphdr)); udp->chksum = 0; if (destip == IP_BROADCAST) { eth_transmit(broadcast, IP, len, buf); } else { long h_netmask = ntohl(netmask); /* Check to see if we need gateway */ if (((destip & h_netmask) != (arptable[ARP_CLIENT].ipaddr & h_netmask)) && arptable[ARP_GATEWAY].ipaddr) destip = arptable[ARP_GATEWAY].ipaddr; for(arpentry = 0; arpentry<MAX_ARP; arpentry++) if (arptable[arpentry].ipaddr == destip) break; if (arpentry == MAX_ARP) { printf("%I is not in my arp table!\n"); return(0); } for (i = 0; i<ETHER_ADDR_LEN; i++) if (arptable[arpentry].node[i]) break; if (i == ETHER_ADDR_LEN) { /* Need to do arp request */ arpreq.hwtype = htons(1); arpreq.protocol = htons(IP); arpreq.hwlen = ETHER_ADDR_LEN; arpreq.protolen = 4; arpreq.opcode = htons(ARP_REQUEST); bcopy(arptable[ARP_CLIENT].node, arpreq.shwaddr, ETHER_ADDR_LEN); convert_ipaddr(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr); bzero(arpreq.thwaddr, ETHER_ADDR_LEN); convert_ipaddr(arpreq.tipaddr, &destip); while (retry--) { eth_transmit(broadcast, ARP, sizeof(arpreq), &arpreq); if (await_reply(AWAIT_ARP, arpentry, arpreq.tipaddr)) goto xmit; } return(0); }xmit: eth_transmit(arptable[arpentry].node, IP, len, buf); } return(1);}/**************************************************************************TFTP - Try to load configuation file**************************************************************************/tftp(name) char *name;{ struct tftp_t *tr; int retry = MAX_TFTP_RETRIES; static unsigned short isocket = 2000; unsigned short osocket = TFTP; unsigned short len, block=1; struct tftp_t tp; int code; printf("Loading %s...\r\n",name); isocket++; tp.opcode = htons(TFTP_RRQ); len = (sprintf((char *)tp.u.rrq,"%s%c%s",name,0,"octet") - ((char *)&tp)) + 1; while(retry--) { if (!udp_transmit(arptable[ARP_SERVER].ipaddr, isocket, osocket, len, &tp)) return(0); if (await_reply(AWAIT_TFTP, isocket, NULL)) { tr = (struct tftp_t *)&packet[ETHER_HDR_LEN]; if (tr->opcode == ntohs(TFTP_ERROR)) { printf("TFTP error %d (%s)\r\n", ntohs(tr->u.err.errcode), tr->u.err.errmsg); return(0); } /* ACK PACKET */ if (tr->opcode != ntohs(TFTP_DATA)) return(0); tp.opcode = htons(TFTP_ACK); tp.u.ack.block = tr->u.data.block; udp_transmit(arptable[ARP_SERVER].ipaddr, isocket, osocket, TFTP_MIN_PACKET_SIZE, &tp); len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 4; if (len >= 512) { printf("Config file too large.\r\n"); config_buffer[0] = 0; return(0); } else { bcopy(tr->u.data.download, config_buffer, len); config_buffer[len] = 0; } return(1); } } return(0);}/**************************************************************************BOOTP - Get my IP address and load information**************************************************************************/bootp(){ int retry = MAX_BOOTP_RETRIES; struct bootp_t bp; unsigned long starttime; bzero(&bp, sizeof(struct bootp_t)); bp.bp_op = BOOTP_REQUEST; bp.bp_htype = 1; bp.bp_hlen = ETHER_ADDR_LEN; bp.bp_xid = starttime = currticks(); bcopy(arptable[ARP_CLIENT].node, bp.bp_hwaddr, ETHER_ADDR_LEN); while(retry--) { udp_transmit(IP_BROADCAST, 0, BOOTP_SERVER, sizeof(struct bootp_t), &bp); if (await_reply(AWAIT_BOOTP, 0, NULL)) return(1); bp.bp_secs = htons((currticks()-starttime)/20); } return(0);}/**************************************************************************AWAIT_REPLY - Wait until we get a response for our request**************************************************************************/await_reply(type, ival, ptr) int type, ival; char *ptr;{ unsigned long time; struct iphdr *ip; struct udphdr *udp; struct arprequest *arpreply; struct bootp_t *bootpreply; struct rpc_t *rpc; int protohdrlen = ETHER_HDR_LEN + sizeof(struct iphdr) + sizeof(struct udphdr); time = currticks() + TIMEOUT; while(time > currticks()) { pollkbd(); if (eth_poll()) { /* We have something! */ /* Check for ARP - No IP hdr */ if ((type == AWAIT_ARP) && (packetlen >= ETHER_HDR_LEN + sizeof(struct arprequest)) && (((packet[12] << 8) | packet[13]) == ARP)) { arpreply = (struct arprequest *) &packet[ETHER_HDR_LEN]; if ((arpreply->opcode == ntohs(ARP_REPLY)) && bcompare(arpreply->sipaddr, ptr, 4)) { bcopy(arpreply->shwaddr, arptable[ival].node, ETHER_ADDR_LEN); return(1); } continue; } /* Anything else has IP header */ if ((packetlen < protohdrlen) || (((packet[12] << 8) | packet[13]) != IP)) continue; ip = (struct iphdr *)&packet[ETHER_HDR_LEN]; if ((ip->verhdrlen != 0x45) || ipchksum(ip, sizeof(struct iphdr)) || (ip->protocol != IP_UDP)) continue; udp = (struct udphdr *)&packet[ETHER_HDR_LEN + sizeof(struct iphdr)]; /* BOOTP ? */ bootpreply = (struct bootp_t *)&packet[ETHER_HDR_LEN]; if ((type == AWAIT_BOOTP) && (packetlen >= (ETHER_HDR_LEN + sizeof(struct iphdr) + sizeof(struct udphdr) + BOOTP_MIN_LEN)) && (ntohs(udp->dest) == BOOTP_CLIENT) && (bootpreply->bp_op == BOOTP_REPLY)) { convert_ipaddr(&arptable[ARP_CLIENT].ipaddr, bootpreply->bp_yiaddr); default_netmask(); convert_ipaddr(&arptable[ARP_SERVER].ipaddr, bootpreply->bp_siaddr); bzero(arptable[ARP_SERVER].node, ETHER_ADDR_LEN); /* Kill arp */ convert_ipaddr(&arptable[ARP_GATEWAY].ipaddr, bootpreply->bp_giaddr); bzero(arptable[ARP_GATEWAY].node, ETHER_ADDR_LEN); /* Kill arp */ if (bootpreply->bp_file[0]) { bcopy(bootpreply->bp_file, kernel_buf, 128); kernel = kernel_buf; } decode_rfc1048(bootpreply->bp_vend); return(1); } /* TFTP ? */ if ((type == AWAIT_TFTP) && (ntohs(udp->dest) == ival)) return(1); /* RPC */ rpc = (struct rpc_t *)&packet[ETHER_HDR_LEN]; if ((type == AWAIT_RPC) && (ntohs(udp->dest) == RPC_SOCKET) && (ntohl(rpc->u.reply.id) == ival) && (ntohl(rpc->u.reply.type) == MSG_REPLY)) { rpc_id++; return(1); } } } return(0);}voidbootp_string(char *name, char *bootp_ptr){ char tmp_buf[512]; /* oversized, but who cares ! */ bzero(tmp_buf, sizeof(tmp_buf)); bcopy(bootp_ptr+2, tmp_buf, TAG_LEN(bootp_ptr)); sprintf(config_buffer+strlen(config_buffer), "%s %s\n", name, tmp_buf);}/**************************************************************************DECODE_RFC1048 - Decodes RFC1048 header**************************************************************************/decode_rfc1048(p) unsigned char *p;{ static char rfc1048_cookie[4] = RFC1048_COOKIE; unsigned char *end = p + BOOTP_VENDOR_LEN,*q; if (bcompare(p, rfc1048_cookie, 4)) { /* RFC 1048 header */ p += 4; while(p < end) { switch (*p) { case RFC1048_PAD: p++; continue; case RFC1048_END: p = end; continue; case RFC1048_GATEWAY: convert_ipaddr(&arptable[ARP_GATEWAY].ipaddr, p+2); break; case RFC1048_NETMASK: bcopy(p+2,&netmask,4); break; case RFC1048_HOSTNAME: bcopy(p+2, &nfsdiskless.my_hostnam, TAG_LEN(p)); hostnamelen = (TAG_LEN(p) + 3) & ~3; break; case RFC1048_ROOT_PATH: /* XXX check len */ bootp_string("rootfs", p); break; case RFC1048_SWAP_PATH: bootp_string("swapfs", p); break; case RFC1048_SWAP_LEN: /* T129 */ sprintf(config_buffer+strlen(config_buffer), "swapsize %d\n", ntohl(*(long *)(p+2)) ); break; case 130: /* root mount options */ bootp_string("rootopts", p); break; case 131: /* swap mount options */ bootp_string("swapopts", p); break; default: printf("Unknown RFC1048-tag "); for(q=p;q<p+2+TAG_LEN(p);q++) printf("%x ",*q); printf("\n\r"); } p += TAG_LEN(p) + 2; } }}/**************************************************************************IPCHKSUM - Checksum IP Header**************************************************************************/ipchksum(ip, len) unsigned short *ip; int len;{ unsigned long sum = 0; len >>= 1; while (len--) { sum += *(ip++); if (sum > 0xFFFF) sum -= 0xFFFF; } return((~sum) & 0x0000FFFF);}/**************************************************************************CONVERT_IPADDR - Convert IP address from net to machine order**************************************************************************/convert_ipaddr(d, s) char *d,*s;{ *(d+3) = *s; *(d+2) = *(s+1); *(d+1) = *(s+2); *d = *(s+3);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -