📄 ethernet.c
字号:
break; case ecs(ETHERTYPE_ARP): arpp = (struct arphdr *)(ehdr+1); printf(" Type = ARP %s from IP %d.%d.%d.%d)\n", arpp->operation == ecs(ARP_RESPONSE) ? "RESPONSE" : "REQUEST", arpp->senderia[0],arpp->senderia[1], arpp->senderia[2],arpp->senderia[3]); break; case ecs(ETHERTYPE_REVARP): printf(" Type = REVARP\n"); break; default: printf(" Type = 0x%04x ???\n", ehdr->ether_type); break; }}/* * printIp(p) */intprintIp(struct ip *ihdr){ int i; struct ip *icpy; char buf[16], buf1[16]; ulong tmp[sizeof(struct ip)/2]; /* Copy data to aligned memory space so printf doesn't crash. */ memcpy((char *)tmp,(char *)ihdr,sizeof(struct ip)); icpy = (struct ip *)tmp; printf(" IP: vhl/tos len id offset ttl/proto csum\n"); printf(" x%02x%02x x%04x x%04x x%04x x%02x%02x x%04x\n", icpy->ip_vhl,icpy->ip_tos, ecs(icpy->ip_len), ecs(icpy->ip_id), ecs(icpy->ip_off), icpy->ip_ttl, icpy->ip_p, ecs(icpy->ip_sum)); printf(" src dest\n"); printf(" %s %s\n", IpToString(icpy->ip_src.s_addr,buf), IpToString(icpy->ip_dst.s_addr,buf1)); if (icpy->ip_p == IP_UDP) { printUdp((struct Udphdr *)(ihdr+1)); return(0); } for(i=0;protocols[i].pname;i++) { if (icpy->ip_p == protocols[i].pnum) { printf(" Protocol: %s\n",protocols[i].pname); return(0); } } printf(" <%02x>: unknown IP protocol\n", icpy->ip_p); return (1);}/* * printUdp(p) */intprintUdp(struct Udphdr *p){ ushort dport, sport; dport = ecs(p->uh_dport); sport = ecs(p->uh_sport);#if INCLUDE_DHCPBOOT if ((dport == DhcpServerPort) || (dport == DhcpClientPort)) { printDhcp(p); return(0); }#endif printf(" UDP: sport dport ulen sum\n"); printf(" %4d %4d %4d %4d\n", sport, dport, ecs(p->uh_ulen),ecs(p->uh_sum)); return(0);}intIpToBin(char *ascii,uchar *binary){ int i, digit; char *acpy; acpy = ascii; for(i=0;i<4;i++) { digit = (int)strtol(acpy,&acpy,10); if (((i != 3) && (*acpy++ != '.')) || ((i == 3) && (*acpy != 0)) || (digit < 0) || (digit > 255)) { printf("Misformed IP addr: %s\n",ascii); return(-1); } binary[i] = (uchar)digit; } return(0);}/* IpToString(): * Incoming ascii pointer is assumed to be pointing to at least 16 * characters of available space. Conversion from long to ascii is done * and string is terminated with NULL. The ascii pointer is returned. */char *IpToString(ulong ipadd,char *ascii){ uchar *cp; cp = (uchar *)&ipadd; sprintf(ascii,"%d.%d.%d.%d", (int)cp[0],(int)cp[1],(int)cp[2],(int)cp[3]); return(ascii);}char *EtherToString(uchar *etheradd,char *ascii){ sprintf(ascii,"%02x:%02x:%02x:%02x:%02x:%02x",(int)etheradd[0], (int)etheradd[1],(int)etheradd[2],(int)etheradd[3], (int)etheradd[4],(int)etheradd[5]); return(ascii);}/* ipChksum(): * Compute the checksum of the IP header. * The incoming pointer to an IP header is directly populated with * the result. */voidipChksum(struct ip *ihdr){ register int i; register ushort *sp; register long csum; csum = 0; ihdr->ip_sum = 0; sp = (ushort *) ihdr; for (i=0;i<((int)sizeof(struct ip)/(int)sizeof(ushort));i++,sp++) { csum += *sp; if (csum & 0x80000000) csum = (csum & 0xffff) + (csum >> 16); } while(csum >> 16) csum = (csum & 0xffff) + (csum >> 16); ihdr->ip_sum = ~csum;}/* udpChksum(): * Compute the checksum of the UDP packet. * The incoming pointer is to an ip header, the udp header after that ip * header is directly populated with the result. * Got part of this code out of Steven's TCP/IP Illustrated Volume 2. */voidudpChksum(struct ip *ihdr){ register int i; register ushort *datap; register long sum; int len; struct Udphdr *uhdr; struct UdpPseudohdr pseudohdr; uhdr = (struct Udphdr *)(ihdr+1); uhdr->uh_sum = 0; /* Note that optionally, the checksum can be forced to zero here, * so a return could replace the remaining code. * That would be kinda dangerous, but it is an option according to * the spec. */ /* Start with the checksum of the pseudo header: * Note that we have to use memcpy because we don't know if the incoming * stream is aligned properly. */ memcpy((char *)&pseudohdr.ip_src.s_addr,(char *)&ihdr->ip_src.s_addr,4); memcpy((char *)&pseudohdr.ip_dst.s_addr,(char *)&ihdr->ip_dst.s_addr,4); pseudohdr.zero = 0; pseudohdr.proto = ihdr->ip_p; pseudohdr.ulen = uhdr->uh_ulen; /* Get checksum of pseudo header: */ sum = 0; datap = (ushort *) &pseudohdr; for (i=0;i<(sizeof(struct UdpPseudohdr)/sizeof(ushort));i++) { sum += *datap++; if (sum & 0x80000000) sum = (sum & 0xffff) + (sum >> 16); } len = ecs(uhdr->uh_ulen); datap = (ushort *) uhdr; /* If length is odd, pad with zero and add 1... */ if (len & 1) { uchar *ucp; ucp = (uchar *)uhdr; ucp[len] = 0; len++; } while(len) { sum += *datap++; if (sum & 0x80000000) sum = (sum & 0xffff) + (sum >> 16); len -= 2; } while(sum >> 16) sum = (sum & 0xffff) + (sum >> 16); uhdr->uh_sum = ~sum;}struct ether_header *EtherCopy(struct ether_header *re){ struct ether_header *te; te = (struct ether_header *) getXmitBuffer(); memcpy((char *)&(te->ether_shost),(char *)&(re->ether_dhost),6); memcpy((char *)&(te->ether_dhost),(char *)&(re->ether_shost),6); te->ether_type = re->ether_type; return(te);}ushortipId(void){ return(++UniqueIpId);}/* getTuneup(): * The DHCP, TFTP and ARP timeout & retry mechanism can be tuned based on * the content of the shell variables DHCPRETRYTUNE, TFTPRETRYTUNE and * ARPRETRYTUNE respectively. * Return 0 if variable is not found, -1 if there is a detected error in * the content of the shell variable; else 1 indicating that the three * parameters have been loaded from the content of the shell variable. */intgetTuneup(char *varname,int *rexmitdelay,int *giveupcount,int *rexmitdelaymax){ char *vp, *colon1, *colon2; vp = getenv(varname); if (!vp) return(0); colon1 = strchr(vp,':'); if (colon1) { colon2 = strchr(colon1+1,':'); if (colon2) { *rexmitdelay = (int)strtol(vp,0,0); *giveupcount = (int)strtol(colon1+1,0,0); *rexmitdelaymax = (int)strtol(colon2+1,0,0); return(1); } } printf("Syntax error in %s\n",varname); return(-1);}/* RetransmitDelay(): * This function provides a common point for retransmission delay * calculation. It is an implementation "similar" to the recommendation * made in the RFC 2131 (DHCP) section 4.1 paragraph #8... * * The delay before the first retransmission is 4 seconds randomized by * the value of a uniform random number chosen from the range -1 to +2. * The delay before the next retransmission is 8 seconds randomized by * the same number as previous randomization. Each subsequent retransmission * delay is doubled up to a maximum of 66 seconds. Once a delay of 66 * seconds is reached, return that value for for 6 subsequent delay * requests, then return RETRANSMISSION_TIMEOUT (-1) indicating that the * requestor should give up. * * The value of randomdelta will be 2, 1, 0 or -1 depending on the target's * IP address. * * The return values will be... * 4+randomdelta, 8+randomdelta, 16+randomdelta, etc... up to 64+randomdelta. * Then after returning 64+randomdelta 6 times, return RETRANSMISSION_TIMEOUT. * * NOTE: if DELAY_RETURN is the opcode, then RETRANSMISSION_TIMEOUT is * never returned, once the max is reached, it is always the value * returned; * if DELAY_OR_TIMEOUT_RETURN is the opcode, then once maxoutcount * reaches 6, RETRANSMISSION_TIMEOUT is returned. * * NOTE1: this function supports the ability to modify the above-discussed * parameters. Start with DELAY_INIT_DHCP to set up the parameters * discussed above; start with DELAY_INIT_XXXX for others. */intRetransmitDelay(int opcode){ static int randomdelta; /* Used to slightly randomize the delay. * Taken from the 2 least-significant-bits * of the IP address (range = -1 to 2). */ static int rexmitdelay; /* Doubled each time DELAY_INCREMENT * is called until it is greater than the * value stored in rexmitdelaymax. */ static int rexmitdelaymax; /* See rexmitdelay. */ static int maxoutcount; /* Number of times the returned delay has * reached its max. */ static int giveupcount; /* Once maxoutcount reaches this value, we * give up and return TIMEOUT. */ int rexmitstate; rexmitstate = RETRANSMISSION_ACTIVE; switch(opcode) { case DELAY_INIT_DHCP: if (getTuneup("DHCPRETRYTUNE",&rexmitdelay, &giveupcount,&rexmitdelaymax) <= 0) { rexmitdelay = 4; giveupcount = 6; rexmitdelaymax = 64; } maxoutcount = 0; randomdelta = (int)(BinIpAddr[3] & 3) - 1; break; case DELAY_INIT_TFTP: if (getTuneup("TFTPRETRYTUNE",&rexmitdelay, &giveupcount,&rexmitdelaymax) <= 0) { rexmitdelay = 4; giveupcount = 3; rexmitdelaymax = 32; } maxoutcount = 0; randomdelta = (int)(BinIpAddr[3] & 3) - 1; break; case DELAY_INIT_ARP: if (getTuneup("ARPRETRYTUNE",&rexmitdelay, &giveupcount,&rexmitdelaymax) <= 0) { rexmitdelay = 1; giveupcount = 0; rexmitdelaymax = 4; } maxoutcount = 0; randomdelta = 0; break; case DELAY_INCREMENT: if (rexmitdelay < rexmitdelaymax) rexmitdelay <<= 1; /* double it. */ else maxoutcount++; if (maxoutcount > giveupcount) rexmitstate = RETRANSMISSION_TIMEOUT; break; case DELAY_OR_TIMEOUT_RETURN: if (maxoutcount > giveupcount) rexmitstate = RETRANSMISSION_TIMEOUT; break; case DELAY_RETURN: break; default: printf("\007TimeoutAlgorithm error 0x%x.\n",opcode); rexmitstate = RETRANSMISSION_TIMEOUT; break; } if (rexmitstate == RETRANSMISSION_TIMEOUT) return(RETRANSMISSION_TIMEOUT); else return(rexmitdelay+randomdelta);}#endif/* EtherToBin(): * Convert ascii MAC address string to binary. Note that this is outside * the #if INCLUDE_ETHERNET because it is used by password.c. This correctly * implies that if there is no ethernet interface, then we need a different * solution for the password backdoor!. */intEtherToBin(char *ascii,uchar *binary){ int i, digit; char *acpy; acpy = ascii; for(i=0;i<6;i++) { digit = (int)strtol(acpy,&acpy,16); if (((i != 5) && (*acpy++ != ':')) || ((i == 5) && (*acpy != 0)) || (digit < 0) || (digit > 255)) { printf("Misformed ethernet addr: %s\n",ascii); return(-1); } binary[i] = (uchar)digit; } return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -