diff options
Diffstat (limited to 'main/common/icmp.c')
-rw-r--r-- | main/common/icmp.c | 1022 |
1 files changed, 517 insertions, 505 deletions
diff --git a/main/common/icmp.c b/main/common/icmp.c index 51b2c5a..74900be 100644 --- a/main/common/icmp.c +++ b/main/common/icmp.c @@ -1,7 +1,7 @@ /************************************************************************** * * Copyright (c) 2013 Alcatel-Lucent - * + * * Alcatel Lucent licenses this file to You under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. A copy of the License is contained the @@ -48,511 +48,521 @@ #define MSECS_PER_MINUTE 60000 #define MSECS_PER_SECOND 1000 -#define ICMP_TIME_ID 0x1111 /* made these up. */ -#define ICMP_ECHO_ID 0x2222 -#define ICMP_ECHO_DATASIZE 26 +#define ICMP_TIME_ID 0x1111 /* made these up. */ +#define ICMP_ECHO_ID 0x2222 +#define ICMP_ECHO_DATASIZE 26 #if INCLUDE_ICMPTIME -static ulong ICMPTimeStamp; +static ulong ICMPTimeStamp; #endif -static int CheckSrvrResolution; -ushort ICMPEchoReplyId, ICMPSeqNoRcvd; -int SendICMPRequest(uchar,uchar *,uchar *,ulong,ushort); +static int CheckSrvrResolution; +ushort ICMPEchoReplyId, ICMPSeqNoRcvd; +int SendICMPRequest(uchar,uchar *,uchar *,ulong,ushort); int SendEchoResp(struct ether_header *); /* Destination unreachable codes: (3rd Edition Comer pg 129) */ -char *IcmpDestUnreachableCode[] = { - "Network unreachable", - "Host unreachable", - "Protocol unreachable", - "Port unreachable", - "Fragmentation needed and DF set", - "Source route failed", - "???", +char *IcmpDestUnreachableCode[] = { + "Network unreachable", + "Host unreachable", + "Protocol unreachable", + "Port unreachable", + "Fragmentation needed and DF set", + "Source route failed", + "???", }; char *IcmpHelp[] = { - "ICMP interface", - "-[c:d:f:rs:t:v:] {operation} [args]", + "ICMP interface", + "-[c:d:f:rs:t:v:] {operation} [args]", #if INCLUDE_VERBOSEHELP - "Options...", - " -c {#} echo count", - " -s {#} size of icmp-echo packet", - " -t {#} timeout (msec) to wait for response (default=2000)", - " -v {var} load result in shellvar 'var'", + "Options...", + " -c {#} echo count", + " -s {#} size of icmp-echo packet", + " -t {#} timeout (msec) to wait for response (default=2000)", + " -v {var} load result in shellvar 'var'", #if INCLUDE_ICMPTIME - " -d {#} delta (hours) relative to GMT", - " -f {x|d} hex or decimal output (default is ascii)", - " -r check server resolution", - "Operations...", - " time {IP}", - " echo {IP}", - "Notes...", - " If '.ns' is appended to time, then time is non-standard.", - " The 'dfr' options are used by time, options 'cs' are used by echo.", + " -d {#} delta (hours) relative to GMT", + " -f {x|d} hex or decimal output (default is ascii)", + " -r check server resolution", + "Operations...", + " time {IP}", + " echo {IP}", + "Notes...", + " If '.ns' is appended to time, then time is non-standard.", + " The 'dfr' options are used by time, options 'cs' are used by echo.", #endif #endif - 0, + 0, }; int Icmp(int argc,char *argv[]) { - ushort seqno; - long size; - struct elapsed_tmr tmr; - int opt, count, timeout; - uchar binip[8], binenet[8]; - char *varname, *operation, *ipadd; + ushort seqno; + long size; + struct elapsed_tmr tmr; + int opt, count, timeout; + uchar binip[8], binenet[8]; + char *varname, *operation, *ipadd; #if INCLUDE_ICMPTIME - uchar buf[32]; - char *nonstandard = "", format='a'; - int timestamp, hour, min, sec, gmt_delta=0; + uchar buf[32]; + char *nonstandard = "", format='a'; + int timestamp, hour, min, sec, gmt_delta=0; #endif - size = 0; - count = 1; - timeout = 2000; - varname = (char *)0; - CheckSrvrResolution = 0; - - while ((opt=getopt(argc,argv,"c:d:f:rs:t:v:")) != -1) { - switch(opt) { - case 'c': /* count used by ping */ - count = strtol(optarg,(char **)0,0); - break; + size = 0; + count = 1; + timeout = 2000; + varname = (char *)0; + CheckSrvrResolution = 0; + + while((opt=getopt(argc,argv,"c:d:f:rs:t:v:")) != -1) { + switch(opt) { + case 'c': /* count used by ping */ + count = strtol(optarg,(char **)0,0); + break; #if INCLUDE_ICMPTIME - case 'd': /* difference between this time zone and Greenwich */ - gmt_delta = strtol(optarg,(char **)0,0); - break; - case 'f': - format = *optarg; - break; - case 'r': - CheckSrvrResolution = 1; - break; + case 'd': /* difference between this time zone and Greenwich */ + gmt_delta = strtol(optarg,(char **)0,0); + break; + case 'f': + format = *optarg; + break; + case 'r': + CheckSrvrResolution = 1; + break; #endif - case 's': - size = strtol(optarg,(char **)0,0); - break; - case 't': - timeout = strtol(optarg,(char **)0,0); - break; - case 'v': - varname = optarg; - break; - default: - return(CMD_PARAM_ERROR); - } - } - - if (argc == optind) - return(CMD_PARAM_ERROR); - - operation = argv[optind]; - ipadd = argv[optind+1]; - - /* If time or echo, do the common up-front stuff here... */ - if (!strcmp(operation,"time") || !strcmp(operation,"echo")) { - if (argc != optind + 2) - return(CMD_PARAM_ERROR); - - /* Convert IP address to binary: */ - if (IpToBin(ipadd,binip) < 0) - return(CMD_SUCCESS); - } + case 's': + size = strtol(optarg,(char **)0,0); + break; + case 't': + timeout = strtol(optarg,(char **)0,0); + break; + case 'v': + varname = optarg; + break; + default: + return(CMD_PARAM_ERROR); + } + } + + if(argc == optind) { + return(CMD_PARAM_ERROR); + } + + operation = argv[optind]; + ipadd = argv[optind+1]; + + /* If time or echo, do the common up-front stuff here... */ + if(!strcmp(operation,"time") || !strcmp(operation,"echo")) { + if(argc != optind + 2) { + return(CMD_PARAM_ERROR); + } + + /* Convert IP address to binary: */ + if(IpToBin(ipadd,binip) < 0) { + return(CMD_SUCCESS); + } + } #if INCLUDE_ICMPTIME - if (!strcmp(operation, "time")) { - - /* Get the ethernet address for the IP: */ - if (!ArpEther(binip,binenet,0)) { - printf("ARP failed for %s\n",ipadd); - return(CMD_FAILURE); - } - - ICMPTimeStamp = INVALID_TIMESTAMP; - SendICMPRequest(ICMP_TIMEREQUEST,binip,binenet,0,0); - - /* Limit the amount of time waiting for a response... */ - startElapsedTimer(&tmr,timeout); - while(msecElapsed(&tmr)) { - pollethernet(); - if (ICMPTimeStamp != INVALID_TIMESTAMP) - break; - } - if (ELAPSED_TIMEOUT(&tmr)) { - printf("No response\n"); - return(CMD_FAILURE); - } - - if (ICMPTimeStamp & NONSTANDARD_TIMESTAMP) { - ICMPTimeStamp &= ~NONSTANDARD_TIMESTAMP; - nonstandard = ".ns"; - } - - if (format == 'a') { - timestamp = ICMPTimeStamp + (gmt_delta*MSECS_PER_HOUR); - hour = timestamp/MSECS_PER_HOUR; - timestamp -= hour*MSECS_PER_HOUR; - min = timestamp/MSECS_PER_MINUTE; - timestamp -= min*MSECS_PER_MINUTE; - sec = timestamp/MSECS_PER_SECOND; - timestamp -= sec*MSECS_PER_SECOND; - sprintf((char *)buf,"%02d:%02d:%02d.%03d%s",hour,min,sec,timestamp, - nonstandard); - } - else if (format == 'x') - sprintf((char *)buf,"0x%lx%s",ICMPTimeStamp,nonstandard); - else if (format == 'd') - sprintf((char *)buf,"%ld%s",ICMPTimeStamp,nonstandard); - else - return(CMD_PARAM_ERROR); - if (varname) - setenv(varname,(char *)buf); - else if (!CheckSrvrResolution) - printf("%s\n",buf); - CheckSrvrResolution = 0; - } - else + if(!strcmp(operation, "time")) { + + /* Get the ethernet address for the IP: */ + if(!ArpEther(binip,binenet,0)) { + printf("ARP failed for %s\n",ipadd); + return(CMD_FAILURE); + } + + ICMPTimeStamp = INVALID_TIMESTAMP; + SendICMPRequest(ICMP_TIMEREQUEST,binip,binenet,0,0); + + /* Limit the amount of time waiting for a response... */ + startElapsedTimer(&tmr,timeout); + while(msecElapsed(&tmr)) { + pollethernet(); + if(ICMPTimeStamp != INVALID_TIMESTAMP) { + break; + } + } + if(ELAPSED_TIMEOUT(&tmr)) { + printf("No response\n"); + return(CMD_FAILURE); + } + + if(ICMPTimeStamp & NONSTANDARD_TIMESTAMP) { + ICMPTimeStamp &= ~NONSTANDARD_TIMESTAMP; + nonstandard = ".ns"; + } + + if(format == 'a') { + timestamp = ICMPTimeStamp + (gmt_delta*MSECS_PER_HOUR); + hour = timestamp/MSECS_PER_HOUR; + timestamp -= hour*MSECS_PER_HOUR; + min = timestamp/MSECS_PER_MINUTE; + timestamp -= min*MSECS_PER_MINUTE; + sec = timestamp/MSECS_PER_SECOND; + timestamp -= sec*MSECS_PER_SECOND; + sprintf((char *)buf,"%02d:%02d:%02d.%03d%s",hour,min,sec,timestamp, + nonstandard); + } else if(format == 'x') { + sprintf((char *)buf,"0x%lx%s",ICMPTimeStamp,nonstandard); + } else if(format == 'd') { + sprintf((char *)buf,"%ld%s",ICMPTimeStamp,nonstandard); + } else { + return(CMD_PARAM_ERROR); + } + if(varname) { + setenv(varname,(char *)buf); + } else if(!CheckSrvrResolution) { + printf("%s\n",buf); + } + CheckSrvrResolution = 0; + } else #endif - if (!strcmp(operation, "echo")) { - seqno = 0; - while (count-- > 0) { - - /* Is this a self-ping? */ - if (memcmp((char *)binip,(char *)BinIpAddr,4) == 0) { - printf("Yes, I am alive!\n"); - break; - } - /* Get the ethernet address for the IP: */ - if (!ArpEther(binip,binenet,0)) { - printf("ARP failed for %s\n",ipadd); - if (varname) - setenv(varname,"NOANSWER"); - continue; - } - - ICMPEchoReplyId = 0; - SendICMPRequest(ICMP_ECHOREQUEST,binip,binenet,size,seqno); - - /* Limit the amount of time waiting for a response... */ - startElapsedTimer(&tmr,timeout); - while(!msecElapsed(&tmr)) { - pollethernet(); - if (ICMPEchoReplyId == ICMP_ECHO_ID) - break; - } - - if (ELAPSED_TIMEOUT(&tmr)) { - printf("no answer from %s\n",ipadd); - if (varname) - setenv(varname,"NOANSWER"); - } - else { - printf("%s is alive",ipadd); - if (count) { - printf(" icmp_seq=%d",ICMPSeqNoRcvd); - startElapsedTimer(&tmr,timeout); - while(!msecElapsed(&tmr)) - pollethernet(); - seqno++; - } - if (varname) - setenv(varname,"ALIVE"); - printf("\n"); - } - } - } - else - printf("Unrecognized ICMP op: %s\n",operation); - return(CMD_SUCCESS); + if(!strcmp(operation, "echo")) { + seqno = 0; + while(count-- > 0) { + + /* Is this a self-ping? */ + if(memcmp((char *)binip,(char *)BinIpAddr,4) == 0) { + printf("Yes, I am alive!\n"); + break; + } + /* Get the ethernet address for the IP: */ + if(!ArpEther(binip,binenet,0)) { + printf("ARP failed for %s\n",ipadd); + if(varname) { + setenv(varname,"NOANSWER"); + } + continue; + } + + ICMPEchoReplyId = 0; + SendICMPRequest(ICMP_ECHOREQUEST,binip,binenet,size,seqno); + + /* Limit the amount of time waiting for a response... */ + startElapsedTimer(&tmr,timeout); + while(!msecElapsed(&tmr)) { + pollethernet(); + if(ICMPEchoReplyId == ICMP_ECHO_ID) { + break; + } + } + + if(ELAPSED_TIMEOUT(&tmr)) { + printf("no answer from %s\n",ipadd); + if(varname) { + setenv(varname,"NOANSWER"); + } + } else { + printf("%s is alive",ipadd); + if(count) { + printf(" icmp_seq=%d",ICMPSeqNoRcvd); + startElapsedTimer(&tmr,timeout); + while(!msecElapsed(&tmr)) { + pollethernet(); + } + seqno++; + } + if(varname) { + setenv(varname,"ALIVE"); + } + printf("\n"); + } + } + } else { + printf("Unrecognized ICMP op: %s\n",operation); + } + return(CMD_SUCCESS); } int processICMP(struct ether_header *ehdr,ushort size) { - struct ip *ipp; - struct icmp_hdr *icmpp; - int i; + struct ip *ipp; + struct icmp_hdr *icmpp; + int i; - ipp = (struct ip *)(ehdr + 1); + ipp = (struct ip *)(ehdr + 1); - icmpp = (struct icmp_hdr *)((char *)ipp+IP_HLEN(ipp)); - if (icmpp->type == ICMP_ECHOREQUEST) { /* 3rdEd Comer pg 127 */ + icmpp = (struct icmp_hdr *)((char *)ipp+IP_HLEN(ipp)); + if(icmpp->type == ICMP_ECHOREQUEST) { /* 3rdEd Comer pg 127 */ #if INCLUDE_RARPIPASSIGN - /* If we're here and our IP address is 0.0.0.0, then the - * incoming packet's destination MAC address must have matched - * ours, so we assume (kinda dangerous) that we should assign - * this IP address to ourself... - * This capability allows a board to come up with a MAC address - * assigned, and IP set to 0.0.0.0, then the host can do - * arp -a IPADD MAC - * ping IPADD - * to assing IPADD to this board. - */ - if (DHCPState == DHCPSTATE_NOTUSED) { - if ((BinIpAddr[0] == 0) && (BinIpAddr[1] == 0) && - (BinIpAddr[2] == 0) && (BinIpAddr[3] == 0)) { - memcpy((char *)BinIpAddr,(char *)&(ipp->ip_dst),4); - printf("RARP IP Assignment: %d.%d.%d.%d\n", - BinIpAddr[0], BinIpAddr[1], - BinIpAddr[2], BinIpAddr[3]); - shell_sprintf("IPADD","%d.%d.%d.%d", - BinIpAddr[0], BinIpAddr[1], - BinIpAddr[2], BinIpAddr[3]); - } - } + /* If we're here and our IP address is 0.0.0.0, then the + * incoming packet's destination MAC address must have matched + * ours, so we assume (kinda dangerous) that we should assign + * this IP address to ourself... + * This capability allows a board to come up with a MAC address + * assigned, and IP set to 0.0.0.0, then the host can do + * arp -a IPADD MAC + * ping IPADD + * to assing IPADD to this board. + */ + if(DHCPState == DHCPSTATE_NOTUSED) { + if((BinIpAddr[0] == 0) && (BinIpAddr[1] == 0) && + (BinIpAddr[2] == 0) && (BinIpAddr[3] == 0)) { + memcpy((char *)BinIpAddr,(char *)&(ipp->ip_dst),4); + printf("RARP IP Assignment: %d.%d.%d.%d\n", + BinIpAddr[0], BinIpAddr[1], + BinIpAddr[2], BinIpAddr[3]); + shell_sprintf("IPADD","%d.%d.%d.%d", + BinIpAddr[0], BinIpAddr[1], + BinIpAddr[2], BinIpAddr[3]); + } + } #endif - SendEchoResp(ehdr); - return(0); - } - else if (icmpp->type == ICMP_ECHOREPLY) { - struct icmp_echo_hdr *icmpecho; - - icmpecho = (struct icmp_echo_hdr *)icmpp; - ICMPEchoReplyId = ecs(icmpecho->id); - ICMPSeqNoRcvd = ecs(icmpecho->seq); - } - else if (icmpp->type == ICMP_DESTUNREACHABLE) { /* 3rdEd Comer pg 129 */ + SendEchoResp(ehdr); + return(0); + } else if(icmpp->type == ICMP_ECHOREPLY) { + struct icmp_echo_hdr *icmpecho; + + icmpecho = (struct icmp_echo_hdr *)icmpp; + ICMPEchoReplyId = ecs(icmpecho->id); + ICMPSeqNoRcvd = ecs(icmpecho->seq); + } else if(icmpp->type == ICMP_DESTUNREACHABLE) { /* 3rdEd Comer pg 129 */ #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_INCOMING) { - i = icmpp->code; - if ((i > 5) || (i < 0)) - i = 6; - printf(" ICMP: %s (code=%d)\n", - IcmpDestUnreachableCode[i],icmpp->code); - } + if(EtherVerbose & SHOW_INCOMING) { + i = icmpp->code; + if((i > 5) || (i < 0)) { + i = 6; + } + printf(" ICMP: %s (code=%d)\n", + IcmpDestUnreachableCode[i],icmpp->code); + } #endif - return(0); - } + return(0); + } #if INCLUDE_ICMPTIME - else if (icmpp->type == ICMP_TIMEREPLY) { - struct icmp_time_hdr *icmptime; - ulong orig, recv, xmit; + else if(icmpp->type == ICMP_TIMEREPLY) { + struct icmp_time_hdr *icmptime; + ulong orig, recv, xmit; - icmptime = (struct icmp_time_hdr *)icmpp; - memcpy((char *)&orig,(char *)&icmptime->orig,4); - memcpy((char *)&recv,(char *)&icmptime->recv,4); - memcpy((char *)&xmit,(char *)&icmptime->xmit,4); + icmptime = (struct icmp_time_hdr *)icmpp; + memcpy((char *)&orig,(char *)&icmptime->orig,4); + memcpy((char *)&recv,(char *)&icmptime->recv,4); + memcpy((char *)&xmit,(char *)&icmptime->xmit,4); - ICMPSeqNoRcvd = icmptime->seq; + ICMPSeqNoRcvd = icmptime->seq; #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_INCOMING) { - printf(" ICMP_TIMEREPLY: orig=0x%lx,recv=0x%lx,xmit=0x%lx\n", - orig,recv,xmit); - } + if(EtherVerbose & SHOW_INCOMING) { + printf(" ICMP_TIMEREPLY: orig=0x%lx,recv=0x%lx,xmit=0x%lx\n", + orig,recv,xmit); + } #endif - if (CheckSrvrResolution) { - static int ICMPTimeStampTbl[20]; - - if (icmptime->seq < 20) { - ICMPTimeStampTbl[icmptime->seq] = xmit; - SendICMPRequest(ICMP_TIMEREQUEST,(uchar *)&ipp->ip_src, - (uchar *)&ehdr->ether_shost,0,icmptime->seq+1); - } else { - - printf("TS00: %d\n",ICMPTimeStampTbl[0]); - for(i=1;i<20;i++) { - printf("TS%02d: %d (dlta=%d)\n",i, - ICMPTimeStampTbl[i], - ICMPTimeStampTbl[i]-ICMPTimeStampTbl[i-1]); - } - ICMPTimeStamp = xmit; - } - } - else { - ICMPTimeStamp = xmit; - } - } + if(CheckSrvrResolution) { + static int ICMPTimeStampTbl[20]; + + if(icmptime->seq < 20) { + ICMPTimeStampTbl[icmptime->seq] = xmit; + SendICMPRequest(ICMP_TIMEREQUEST,(uchar *)&ipp->ip_src, + (uchar *)&ehdr->ether_shost,0,icmptime->seq+1); + } else { + + printf("TS00: %d\n",ICMPTimeStampTbl[0]); + for(i=1; i<20; i++) { + printf("TS%02d: %d (dlta=%d)\n",i, + ICMPTimeStampTbl[i], + ICMPTimeStampTbl[i]-ICMPTimeStampTbl[i-1]); + } + ICMPTimeStamp = xmit; + } + } else { + ICMPTimeStamp = xmit; + } + } #endif - else { + else { #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_INCOMING) { - printf(" ICMPTYPE=%d\n",icmpp->type); - } + if(EtherVerbose & SHOW_INCOMING) { + printf(" ICMPTYPE=%d\n",icmpp->type); + } #endif - return(-1); - } - return(0); + return(-1); + } + return(0); } /* SendEchoResp(): - * Called in response to an ICMP ECHO REQUEST. Typically used as - * a response to a PING. + * Called in response to an ICMP ECHO REQUEST. Typically used as + * a response to a PING. */ int SendEchoResp(struct ether_header *re) { - int i, icmp_len, datalen, oddlen; - ulong t; - ushort *sp, ip_len; - struct ether_header *te; - struct ip *ti, *ri; - struct icmp_echo_hdr *ticmp, *ricmp; - - ri = (struct ip *) (re + 1); - datalen = ecs(ri->ip_len) - ((ri->ip_vhl & 0x0f) * 4); - - te = EtherCopy(re); - ti = (struct ip *) (te + 1); - ti->ip_vhl = ri->ip_vhl; - ti->ip_tos = ri->ip_tos; - ti->ip_len = ri->ip_len; - ti->ip_id = ipId(); - ti->ip_off = 0; - ti->ip_ttl = UDP_TTL; - ti->ip_p = IP_ICMP; - memcpy((char *)&(ti->ip_src.s_addr),(char *)&(ri->ip_dst.s_addr), - sizeof(struct in_addr)); - memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), - sizeof(struct in_addr)); - - ticmp = (struct icmp_echo_hdr *) (ti + 1); - ricmp = (struct icmp_echo_hdr *) (ri + 1); - ticmp->type = ICMP_ECHOREPLY; - ticmp->code = 0; - ticmp->cksum = 0; - ticmp->id = ricmp->id; - ticmp->seq = ricmp->seq; - memcpy((char *)(ticmp+1),(char *)(ricmp+1),datalen-8); - - ip_len = ecs(ti->ip_len); - if (ip_len & 1) { /* If size is odd, temporarily bump up ip_len by */ - oddlen = 1; /* one and add append a null byte for csum. */ - ((char *)ti)[ip_len] = 0; - ip_len++; - } - else - oddlen = 0; - icmp_len = (ip_len - sizeof(struct ip))/2; - - ipChksum(ti); /* compute checksum of ip hdr: (3rd Edition Comer pg 100) */ - - /* compute checksum of icmp message: (3rd Edition Comer pg 126) */ - ticmp->cksum = 0; - sp = (ushort *) ticmp; - for (i=0,t=0;i<icmp_len;i++,sp++) - t += ecs(*sp); - t = (t & 0xffff) + (t >> 16); - ticmp->cksum = ~t; - - self_ecs(ticmp->cksum); - - if (oddlen) - ip_len--; - - sendBuffer(sizeof(struct ether_header) + ip_len); + int i, icmp_len, datalen, oddlen; + ulong t; + ushort *sp, ip_len; + struct ether_header *te; + struct ip *ti, *ri; + struct icmp_echo_hdr *ticmp, *ricmp; + + ri = (struct ip *)(re + 1); + datalen = ecs(ri->ip_len) - ((ri->ip_vhl & 0x0f) * 4); + + te = EtherCopy(re); + ti = (struct ip *)(te + 1); + ti->ip_vhl = ri->ip_vhl; + ti->ip_tos = ri->ip_tos; + ti->ip_len = ri->ip_len; + ti->ip_id = ipId(); + ti->ip_off = 0; + ti->ip_ttl = UDP_TTL; + ti->ip_p = IP_ICMP; + memcpy((char *)&(ti->ip_src.s_addr),(char *)&(ri->ip_dst.s_addr), + sizeof(struct in_addr)); + memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), + sizeof(struct in_addr)); + + ticmp = (struct icmp_echo_hdr *)(ti + 1); + ricmp = (struct icmp_echo_hdr *)(ri + 1); + ticmp->type = ICMP_ECHOREPLY; + ticmp->code = 0; + ticmp->cksum = 0; + ticmp->id = ricmp->id; + ticmp->seq = ricmp->seq; + memcpy((char *)(ticmp+1),(char *)(ricmp+1),datalen-8); + + ip_len = ecs(ti->ip_len); + if(ip_len & 1) { /* If size is odd, temporarily bump up ip_len by */ + oddlen = 1; /* one and add append a null byte for csum. */ + ((char *)ti)[ip_len] = 0; + ip_len++; + } else { + oddlen = 0; + } + icmp_len = (ip_len - sizeof(struct ip))/2; + + ipChksum(ti); /* compute checksum of ip hdr: (3rd Edition Comer pg 100) */ + + /* compute checksum of icmp message: (3rd Edition Comer pg 126) */ + ticmp->cksum = 0; + sp = (ushort *) ticmp; + for(i=0,t=0; i<icmp_len; i++,sp++) { + t += ecs(*sp); + } + t = (t & 0xffff) + (t >> 16); + ticmp->cksum = ~t; + + self_ecs(ticmp->cksum); + + if(oddlen) { + ip_len--; + } + + sendBuffer(sizeof(struct ether_header) + ip_len); #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_OUTGOING) - printf(" Sent Echo Response\n"); + if(EtherVerbose & SHOW_OUTGOING) { + printf(" Sent Echo Response\n"); + } #endif - return(0); + return(0); } /* SendICMPRequest(): - * Currently supports ICMP_TIMEREQUEST and ICMP_ECHOREQUEST. + * Currently supports ICMP_TIMEREQUEST and ICMP_ECHOREQUEST. */ int SendICMPRequest(uchar type,uchar *binip,uchar *binenet, - ulong tmpval,ushort seq) + ulong tmpval,ushort seq) { - ushort *sp; - uchar *data; - struct ip *ti; - int i, icmp_len; - struct ether_header *te; - struct icmp_time_hdr *ticmp; - ulong origtime, datasize, csum; - - datasize = ICMP_ECHO_DATASIZE; - - /* Retrieve an ethernet buffer from the driver and populate the */ - /* ethernet level of packet: */ - te = (struct ether_header *) getXmitBuffer(); - memcpy((char *)&te->ether_shost,(char *)BinEnetAddr,6); - memcpy((char *)&te->ether_dhost,(char *)binenet,6); - te->ether_type = ecs(ETHERTYPE_IP); - - /* Move to the IP portion of the packet and populate it appropriately: */ - ti = (struct ip *) (te + 1); - ti->ip_vhl = IP_HDR_VER_LEN; - ti->ip_tos = 0; + ushort *sp; + uchar *data; + struct ip *ti; + int i, icmp_len; + struct ether_header *te; + struct icmp_time_hdr *ticmp; + ulong origtime, datasize, csum; + + datasize = ICMP_ECHO_DATASIZE; + + /* Retrieve an ethernet buffer from the driver and populate the */ + /* ethernet level of packet: */ + te = (struct ether_header *) getXmitBuffer(); + memcpy((char *)&te->ether_shost,(char *)BinEnetAddr,6); + memcpy((char *)&te->ether_dhost,(char *)binenet,6); + te->ether_type = ecs(ETHERTYPE_IP); + + /* Move to the IP portion of the packet and populate it appropriately: */ + ti = (struct ip *)(te + 1); + ti->ip_vhl = IP_HDR_VER_LEN; + ti->ip_tos = 0; #if INCLUDE_ICMPTIME - if (type == ICMP_TIMEREQUEST) { - origtime = tmpval; - ti->ip_len = sizeof(struct ip) + sizeof(struct icmp_time_hdr); - } - else + if(type == ICMP_TIMEREQUEST) { + origtime = tmpval; + ti->ip_len = sizeof(struct ip) + sizeof(struct icmp_time_hdr); + } else #endif - { - if (tmpval != 0) - datasize = tmpval; - ti->ip_len = sizeof(struct ip) + sizeof(struct icmp_echo_hdr) + - datasize; - } - - ti->ip_id = ipId(); - ti->ip_off = 0; - ti->ip_ttl = UDP_TTL; - ti->ip_p = IP_ICMP; - memcpy((char *)&ti->ip_src.s_addr,(char *)BinIpAddr,4); - memcpy((char *)&ti->ip_dst.s_addr,(char *)binip,4); - - icmp_len = (ti->ip_len - sizeof(struct ip))/2; - self_ecs(ti->ip_len); - self_ecs(ti->ip_off); - self_ecs(ti->ip_id); - - ipChksum(ti); /* Compute csum of ip hdr */ - - /* Move to the ICMP portion of the packet and populate it appropriately: */ - ticmp = (struct icmp_time_hdr *)(ti+1); - ticmp->type = type; - ticmp->code = 0; - ticmp->seq = ecs(seq); + { + if(tmpval != 0) { + datasize = tmpval; + } + ti->ip_len = sizeof(struct ip) + sizeof(struct icmp_echo_hdr) + + datasize; + } + + ti->ip_id = ipId(); + ti->ip_off = 0; + ti->ip_ttl = UDP_TTL; + ti->ip_p = IP_ICMP; + memcpy((char *)&ti->ip_src.s_addr,(char *)BinIpAddr,4); + memcpy((char *)&ti->ip_dst.s_addr,(char *)binip,4); + + icmp_len = (ti->ip_len - sizeof(struct ip))/2; + self_ecs(ti->ip_len); + self_ecs(ti->ip_off); + self_ecs(ti->ip_id); + + ipChksum(ti); /* Compute csum of ip hdr */ + + /* Move to the ICMP portion of the packet and populate it appropriately: */ + ticmp = (struct icmp_time_hdr *)(ti+1); + ticmp->type = type; + ticmp->code = 0; + ticmp->seq = ecs(seq); #if INCLUDE_ICMPTIME - if (type == ICMP_TIMEREQUEST) { - ticmp->id = ICMP_TIME_ID; - memcpy((char *)&ticmp->orig,(char *)&origtime,4); - memset((char *)&ticmp->recv,0,4); - memset((char *)&ticmp->xmit,0,4); - } else + if(type == ICMP_TIMEREQUEST) { + ticmp->id = ICMP_TIME_ID; + memcpy((char *)&ticmp->orig,(char *)&origtime,4); + memset((char *)&ticmp->recv,0,4); + memset((char *)&ticmp->xmit,0,4); + } else #endif - { - ticmp->id = ICMP_ECHO_ID; + { + ticmp->id = ICMP_ECHO_ID; - /* Add 'datasize' bytes of data... */ - data = (uchar *)((struct icmp_echo_hdr *)ticmp+1); - for(i=0;i<datasize;i++) - data[i] = 'a'+i; + /* Add 'datasize' bytes of data... */ + data = (uchar *)((struct icmp_echo_hdr *)ticmp+1); + for(i=0; i<datasize; i++) { + data[i] = 'a'+i; + } - } + } - /* compute checksum of icmp message: (3rd Edition Comer pg 126) */ - csum = 0; - ticmp->cksum = 0; - sp = (ushort *) ticmp; - for (i=0;i<icmp_len;i++,sp++) - csum += ecs(*sp); - csum = (csum & 0xffff) + (csum >> 16); - ticmp->cksum = ~csum; + /* compute checksum of icmp message: (3rd Edition Comer pg 126) */ + csum = 0; + ticmp->cksum = 0; + sp = (ushort *) ticmp; + for(i=0; i<icmp_len; i++,sp++) { + csum += ecs(*sp); + } + csum = (csum & 0xffff) + (csum >> 16); + ticmp->cksum = ~csum; - self_ecs(ticmp->cksum); + self_ecs(ticmp->cksum); #if INCLUDE_ICMPTIME - if (type == ICMP_TIMEREQUEST) { - self_ecl(ticmp->orig); - self_ecl(ticmp->recv); - self_ecl(ticmp->xmit); - sendBuffer(ICMP_TIMERQSTSIZE); - } - else + if(type == ICMP_TIMEREQUEST) { + self_ecl(ticmp->orig); + self_ecl(ticmp->recv); + self_ecl(ticmp->xmit); + sendBuffer(ICMP_TIMERQSTSIZE); + } else #endif - sendBuffer(ICMP_ECHORQSTSIZE+datasize); - return(0); + sendBuffer(ICMP_ECHORQSTSIZE+datasize); + return(0); } /* Send an ICMP Unreachable message. All ICMP Unreachable messages @@ -566,81 +576,83 @@ SendICMPRequest(uchar type,uchar *binip,uchar *binenet, int SendICMPUnreachable(struct ether_header *re,uchar icmp_code) { - int i, len; - ushort *sp, r_iphdr_len, ip_len; - ulong t; - struct ether_header *te; - struct ip *ti, *ri; - struct icmp_unreachable_hdr *ticmp; - - /* If DONTSEND_ICMP_UNREACHABLE is set, then don't send out the - * message... - */ - if (getenv("DONTSEND_ICMP_UNREACHABLE")) - return(0); - - ri = (struct ip *) (re + 1); - - /* Length of the received IP hdr */ - r_iphdr_len = ((ri->ip_vhl & 0x0f)<<2); - - te = EtherCopy(re); - - ti = (struct ip *) (te + 1); - ti->ip_vhl = IP_HDR_VER_LEN; - ti->ip_tos = 0; - /* Length of the outgoing IP packet = IP header + ICMP header + - * IP header and 8 bytes of unreachable datagram - */ - ip_len = (IP_HDR_LEN<<2)+sizeof(struct icmp_unreachable_hdr)+r_iphdr_len+8; - ti->ip_len = ecs(ip_len); - ti->ip_id = ipId(); - ti->ip_off = 0; - ti->ip_ttl = UDP_TTL; - ti->ip_p = IP_ICMP; - - /* Note that we do memcpy instead of struct copy because the ip - * header is not not word-aligned. As a result, the source and dest - * addresses are not word aligned either. The compiler generates word - * copy instructions for struct copy and this causes address alignement - * exceptions. - */ - memcpy((char *)&(ti->ip_src.s_addr),(char *)&(ri->ip_dst.s_addr), - sizeof(struct in_addr)); - memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), - sizeof(struct in_addr)); - - ticmp = (struct icmp_unreachable_hdr *) (ti + 1); - ticmp->type = ICMP_DESTUNREACHABLE; - ticmp->code = icmp_code; - ticmp->cksum = 0; - ticmp->unused1=0; - ticmp->unused2=0; - - /* Copy the IP header and 8 bytes of the received datagram */ - memcpy((char *)(ticmp+1),(char *)ri,r_iphdr_len+8); - - ipChksum(ti); /* compute checksum of ip hdr */ - - /* compute checksum of icmp message: (see Comer pg 91) */ - len = (ip_len - sizeof(struct ip))/2; - ticmp->cksum = 0; - sp = (ushort *) ticmp; - for (i=0,t=0;i<len;i++,sp++) - t += ecs(*sp); - t = (t & 0xffff) + (t >> 16); - ticmp->cksum = ~t; - self_ecs(ticmp->cksum); - - sendBuffer(sizeof(struct ether_header) + ip_len); + int i, len; + ushort *sp, r_iphdr_len, ip_len; + ulong t; + struct ether_header *te; + struct ip *ti, *ri; + struct icmp_unreachable_hdr *ticmp; + + /* If DONTSEND_ICMP_UNREACHABLE is set, then don't send out the + * message... + */ + if(getenv("DONTSEND_ICMP_UNREACHABLE")) { + return(0); + } + + ri = (struct ip *)(re + 1); + + /* Length of the received IP hdr */ + r_iphdr_len = ((ri->ip_vhl & 0x0f)<<2); + + te = EtherCopy(re); + + ti = (struct ip *)(te + 1); + ti->ip_vhl = IP_HDR_VER_LEN; + ti->ip_tos = 0; + /* Length of the outgoing IP packet = IP header + ICMP header + + * IP header and 8 bytes of unreachable datagram + */ + ip_len = (IP_HDR_LEN<<2)+sizeof(struct icmp_unreachable_hdr)+r_iphdr_len+8; + ti->ip_len = ecs(ip_len); + ti->ip_id = ipId(); + ti->ip_off = 0; + ti->ip_ttl = UDP_TTL; + ti->ip_p = IP_ICMP; + + /* Note that we do memcpy instead of struct copy because the ip + * header is not not word-aligned. As a result, the source and dest + * addresses are not word aligned either. The compiler generates word + * copy instructions for struct copy and this causes address alignement + * exceptions. + */ + memcpy((char *)&(ti->ip_src.s_addr),(char *)&(ri->ip_dst.s_addr), + sizeof(struct in_addr)); + memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr), + sizeof(struct in_addr)); + + ticmp = (struct icmp_unreachable_hdr *)(ti + 1); + ticmp->type = ICMP_DESTUNREACHABLE; + ticmp->code = icmp_code; + ticmp->cksum = 0; + ticmp->unused1=0; + ticmp->unused2=0; + + /* Copy the IP header and 8 bytes of the received datagram */ + memcpy((char *)(ticmp+1),(char *)ri,r_iphdr_len+8); + + ipChksum(ti); /* compute checksum of ip hdr */ + + /* compute checksum of icmp message: (see Comer pg 91) */ + len = (ip_len - sizeof(struct ip))/2; + ticmp->cksum = 0; + sp = (ushort *) ticmp; + for(i=0,t=0; i<len; i++,sp++) { + t += ecs(*sp); + } + t = (t & 0xffff) + (t >> 16); + ticmp->cksum = ~t; + self_ecs(ticmp->cksum); + + sendBuffer(sizeof(struct ether_header) + ip_len); #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_OUTGOING) - printf(" Sent ICMP Dest Unreachable message. Code='%s'.\n", - IcmpDestUnreachableCode[icmp_code]); + if(EtherVerbose & SHOW_OUTGOING) + printf(" Sent ICMP Dest Unreachable message. Code='%s'.\n", + IcmpDestUnreachableCode[icmp_code]); #endif - return(0); + return(0); } -#endif /* INCLUDE_ICMP */ -#endif /* INCLUDE_ETHERNET */ +#endif /* INCLUDE_ICMP */ +#endif /* INCLUDE_ETHERNET */ |