home *** CD-ROM | disk | FTP | other *** search
- /*
- * IP.C
- * IP level routines, including ICMP
- *
- ****************************************************************************
- * *
- * part of: *
- * TCP/IP kernel for NCSA Telnet *
- * by Tim Krauskopf *
- * *
- * National Center for Supercomputing Applications *
- * 152 Computing Applications Building *
- * 605 E. Springfield Ave. *
- * Champaign, IL 61820 *
- * *
- * Copyright (c) 1987, Board of Trustees of the University of Illinois *
- * *
- ****************************************************************************
- *
- * IP level routines ( including an ICMP handler )
- *
- ****************************************************************************
- * Revision history:
- *
- * May 1993 Jamie Honan
- */
-
- /*
- * Includes
- */
- #include "protocol.h"
- #include "bootinc.h"
-
- ICMPKT blankicmp;
-
- extern int SQwait;
- extern int OKpackets;
-
- /*
- * ipdump ( p )
- *
- * Routine to dump an IP packet -- only compiled if the debug option is
- * enabled.
- */
- void
- ipdump(p)
- IPKT *p;
- {
- uint16 iplen,
- iid;
-
- iid = intswap(p->i.ident);
- iplen = intswap(p->i.tlen);
-
- n_puts("IP packet:");
- n_printf("Version+hdr: %x service %d tlen %u \n",
- p->i.versionandhdrlen, p->i.service, iplen);
- n_printf("Ident: %u frags: %x ttl: %d prot: %d \n",
- iid, p->i.frags, p->i.ttl, p->i.protocol);
- n_printf("addresses: s: %d.%d.%d.%d t: %d.%d.%d.%d \n",
- p->i.ipsource[0], p->i.ipsource[1], p->i.ipsource[2], p->i.ipsource[3],
- p->i.ipdest[0], p->i.ipdest[1], p->i.ipdest[2], p->i.ipdest[3]);
- n_puts("\n");
- }
-
- /***************************************************************************/
- /* neticmpturn
- *
- * 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
- neticmpturn(ICMPKT * p, int ilen)
- {
-
- /*
- * reverse the addresses, dlayer and IP layer
- */
- if (!memcmp(p->d.me, broadaddr, DADDLEN))
- return (0);
-
- memcpy(p->d.dest, p->d.me, DADDLEN);
-
- memcpy(p->i.ipdest, p->i.ipsource, 4);
- memcpy(p->d.me, nnmyaddr, DADDLEN);
- memcpy(p->i.ipsource, nnipnum, 4);
- /*
- * prepare ICMP checksum
- */
- p->c.check = 0;
- p->c.check = ipcheck((char *) &p->c, ilen >> 1);
- /*
- * iplayer for send
- */
- p->i.ident = intswap(nnipident++);
- p->i.check = 0;
- p->i.check = ipcheck((char *) &p->i, 10);
- /*
- * send it
- */
- return ((int) dlayersend((DLAYER *) p, sizeof(DLAYER) + sizeof(IPLAYER) + ilen));
- }
-
-
- /****************************************************************************/
- /*
- * icmpinterpret ( p, icmplen )
- *
- * Interpret the icmp message that just came off the wire
- *
- */
- int
- icmpinterpret(ICMPKT * p, int icmplen)
- {
- uint i;
-
- i = p->c.type;
-
- if (p->c.check)
- { /* ignore if chksum=0 */
- if (ipcheck((char *) &p->c, icmplen >> 1))
- {
- netposterr(699);
- return (0);
- }
- }
- switch (i)
- {
- case 8: /* ping request sent to me */
- p->c.type = 0; /* echo reply type */
- neticmpturn(p, icmplen); /* send back */
- break;
-
- case 5: /* ICMP redirect */
- break;
-
- case 4: /* ICMP source quench */
- VPRINT("ICMP: source quench received");
- OKpackets = 0;
- SQwait += 100;
- break;
-
- case 0: /* ping reply ? */
- break;
-
- case 3: /* destination unreachable */
- return -(630 + p->c.code);
- default:
- break;
- }
- netposterr(600 + i); /* provide info for higher layer user */
- return (0);
- }
-
- /*
- * iprecv ( )
- *
- * Called by the udp layer to get next packet
- * validity of the packet (checksum, flags) and then passes it on to the
- * appropriate protocol handler.
- * Returns length of packet
- */
- unsigned char junk[] = {0, 0, 0, 0};
-
- int
- iprecv(IPKT *p) /* ptr to packet from network */
- {
- int iplen,
- i;
- int retcode;
-
- retcode = ethrecv(p);
- if (retcode == 0)
- return 0;
- if (retcode < 0)
- return retcode;
- /*
- * We cannot handle fragmented IP packets yet, return an error
- */
- if (p->i.frags & 0x20)
- { /* check for a fragmented packet */
- netposterr(304);
- return (0);
- }
- /*
- * checksum verification of IP header
- */
- if (p->i.check)
- { /* no IP checksumming if check=0 */
- if (ipcheck(&p->i.versionandhdrlen, (p->i.versionandhdrlen & 0x0f) << 1))
- {
- netposterr(300); /* bad IP checksum */
- return (0); /* drop packet */
- }
- }
- /*
- * Extract total length of packet
- */
- iplen = intswap(p->i.tlen);
- /*
- * check to make sure that the packet is for me.
- * Throws out all packets which are not directed to my IP address.
- */
- /* n_printf("ip nnipnum %d.%d.%d.%d, dest %d.%d.%d.%d\n",
- nnipnum[0], nnipnum[1], nnipnum[2], nnipnum[3],
- p->i.ipdest[0],
- p->i.ipdest[1],
- p->i.ipdest[2],
- p->i.ipdest[3]);
- */
- if (memcmp(nnipnum, p->i.ipdest, 4)) /* not for me */
- { /* potential non-match */
- if (!memcmp(nnipnum, junk, 4) && p->i.protocol == PROTUDP)
- {
- i = (p->i.versionandhdrlen & 0x0f) << 2;
- return (iplen - i);
- }
- return (0); /* drop packet */
- }
- /*
- * 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 = (p->i.versionandhdrlen & 0x0f) << 2;
- if (i > 20)
- { /* check for options in packet */
- netposterr(302);
- return (0);
- }
- if (debug)
- {
- n_printf("Rx---->\n");
- ipdump(p);
- }
- switch (p->i.protocol)
- { /* which protocol to handle this packet? */
- case PROTUDP:
- return (iplen - i);
- case PROTICMP:
- retcode = icmpinterpret((ICMPKT *) p, iplen - i);
- return retcode;
- default:
- return (0);
- }
- }
-
-