/* ip.c */ /* * IP level routines ( including an ICMP handler ) */ /* * Includes */ #include #include "vtcpip.h" #include "dfault.h" #include "evtdef.h" #include "hstdef.h" #include "prodef.h" #include "prodat.h" #include "tcpdat.h" #include "bytprc.h" #include "hdrchk.h" /* * ipinterpret * * Called by the packet demuxer to interpret a new ip packet. Checks the * validity of the packet (checksum, flags) and then passes it on to the * appropriate protocol handler. * */ int ipinterpret(pkt) register IPKT *pkt; { int iplen,i; /* * We cannot handle fragmented IP packets yet, return an error */ if(pkt->i.frags&0x20) { ntposterr(304); return(1); } /* * checksum verification of IP header * no IP checksumming if check=0 */ if (pkt->i.check) { if(ipcheck(&pkt->i.versionandhdrlen, (pkt->i.versionandhdrlen&0x0f) << 1)) { ntposterr(300); /* bad IP checksum */ return(1); /* drop packet */ } } /* * Check to make sure that the packet is for me. * Accepts packets if my IP address is 0.0.0.0 (not yet defined) * or the packets are directed to my IP address. * * Throws out all other packets. */ if(!comparen(nnipnum,pkt->i.ipdest,4) && nnipnum[0]|nnipnum[1]|nnipnum[2]|nnipnum[3]) { return(1); } /* * Extract total length of packet */ iplen=intswap(pkt->i.tlen); /* * See if there are any IP options to be handled. * We don't understand IP options, post a warning * to the user and drop the packet. */ i=(pkt->i.versionandhdrlen&0x0f)<<2; if(i>20) { ntposterr(302); return(1); } /* * which protocol to handle this packet? */ switch (pkt->i.protocol) { case PROTUDP: return(udpinterpret((UDPKT *)pkt,iplen-i)); case PROTTCP: return(tcpinterpret((TCPKT *)pkt,iplen-i)); case PROTICMP: return(icmpinterpret((ICMPKT *)pkt,iplen-i)); default: ntposterr(303); return(1); } return(0); } /* * icmpinterpret * * Interpret the icmp message that just came off the wire * */ int icmpinterpret(pkt,icmplen) register ICMPKT *pkt; int icmplen; { unsigned int i; register IPLAYER *iptr; #ifdef DEBUGOPTION if(debug&0x84) { dmpfil("icmpin",(ICMPKT *)pkt,sizeof(DLAYER)+sizeof(IPLAYER)+icmplen); } #endif i=pkt->c.type; ntposterr(600+i); if(pkt->c.check) { if(ipcheck((char *)&pkt->c,icmplen>>1)) { ntposterr(699); return(-1); } } switch (i) { /* * ping request sent to me */ case 8: pkt->c.type=0; nticmpturn(pkt,icmplen); break; /* * ICMP redirect */ case 5: iptr=(IPLAYER *)pkt->data; ntptuev(ICMPCLASS,IREDIR,0); movebytes(nnsaveicmp,iptr->ipdest,4); movebytes(nnnewicmp,&pkt->c.part1,4); break; default: break; } return(0); } /* * nticmpturn * * send out an icmp packet, probably in response to a ping operation * interchanges the source and destination addresses of the packet, * puts in my addresses for the source and sends it * * does not change any of the ICMP fields, just the IP and dlayers * returns 0 on okay send, nonzero on error */ int nticmpturn(pkt,ilen) register ICMPKT *pkt; int ilen; { int icmplen; /* * reverse the addresses, dlayer and IP layer */ if (comparen(pkt->d.me,broadaddr,DADDLEN)) return(0); movebytes(pkt->d.dest,pkt->d.me,DADDLEN); movebytes(pkt->i.ipdest,pkt->i.ipsource,4); movebytes(pkt->d.me,nnmyaddr,DADDLEN); movebytes(pkt->i.ipsource,nnipnum,4); /* * prepare ICMP checksum */ pkt->c.check=0; pkt->c.check=ipcheck((char *)&pkt->c,ilen>>1); /* * iplayer for send */ pkt->i.identity=intswap(nnipident++); pkt->i.check=0; pkt->i.check=ipcheck((char *)&pkt->i,10); icmplen = sizeof(DLAYER) + sizeof(IPLAYER) + ilen; /* * send it */ #ifdef DEBUGOPTION if(debug&0x84) { dmpfil("nticmp",(DLAYER *)pkt,icmplen); } #endif return(dlsend((DLAYER *)pkt,icmplen)); }