home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / linux_bo / netboot.zoo / ip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-04  |  6.3 KB  |  252 lines

  1. /*
  2. *   IP.C
  3. *   IP level routines, including ICMP
  4. *
  5. ****************************************************************************
  6. *                                                                          *
  7. *      part of:                                                            *
  8. *      TCP/IP kernel for NCSA Telnet                                       *
  9. *      by Tim Krauskopf                                                    *
  10. *                                                                          *
  11. *      National Center for Supercomputing Applications                     *
  12. *      152 Computing Applications Building                                 *
  13. *      605 E. Springfield Ave.                                             *
  14. *      Champaign, IL  61820                                                *
  15. *                                                                          *
  16. *    Copyright (c) 1987, Board of Trustees of the University of Illinois   *
  17. *                                                                          *
  18. ****************************************************************************
  19. *
  20. *   IP level routines ( including an ICMP handler )
  21. *
  22. ****************************************************************************
  23. *  Revision history:
  24. *
  25. *  May 1993 Jamie Honan
  26. */
  27.  
  28. /*
  29. *   Includes
  30. */
  31. #include "protocol.h"
  32. #include "bootinc.h"
  33.  
  34. ICMPKT          blankicmp;
  35.  
  36. extern int      SQwait;
  37. extern int      OKpackets;
  38.  
  39.  /*
  40.   * ipdump ( p )
  41.   * 
  42.   * Routine to dump an IP packet -- only compiled if the debug option is
  43.   * enabled.
  44.   */
  45. void 
  46. ipdump(p)
  47. IPKT           *p;
  48. {
  49.     uint16          iplen,
  50.                     iid;
  51.  
  52.     iid = intswap(p->i.ident);
  53.     iplen = intswap(p->i.tlen);
  54.  
  55.     n_puts("IP packet:");
  56.     n_printf("Version+hdr: %x     service %d      tlen %u   \n",
  57.            p->i.versionandhdrlen, p->i.service, iplen);
  58.     n_printf("Ident: %u    frags: %x    ttl: %d    prot: %d  \n",
  59.            iid, p->i.frags, p->i.ttl, p->i.protocol);
  60.     n_printf("addresses: s: %d.%d.%d.%d    t: %d.%d.%d.%d \n",
  61.            p->i.ipsource[0], p->i.ipsource[1], p->i.ipsource[2], p->i.ipsource[3],
  62.         p->i.ipdest[0], p->i.ipdest[1], p->i.ipdest[2], p->i.ipdest[3]);
  63.     n_puts("\n");
  64. }
  65.  
  66. /***************************************************************************/
  67. /*  neticmpturn
  68. *
  69. *   send out an icmp packet, probably in response to a ping operation
  70. *   interchanges the source and destination addresses of the packet,
  71. *   puts in my addresses for the source and sends it
  72. *
  73. *   does not change any of the ICMP fields, just the IP and dlayers
  74. *   returns 0 on okay send, nonzero on error
  75. */
  76. int 
  77. neticmpturn(ICMPKT * p, int ilen)
  78. {
  79.  
  80. /*
  81. *  reverse the addresses, dlayer and IP layer
  82. */
  83.     if (!memcmp(p->d.me, broadaddr, DADDLEN))
  84.         return (0);
  85.  
  86.     memcpy(p->d.dest, p->d.me, DADDLEN);
  87.  
  88.     memcpy(p->i.ipdest, p->i.ipsource, 4);
  89.     memcpy(p->d.me, nnmyaddr, DADDLEN);
  90.     memcpy(p->i.ipsource, nnipnum, 4);
  91. /*
  92. *  prepare ICMP checksum
  93. */
  94.     p->c.check = 0;
  95.     p->c.check = ipcheck((char *) &p->c, ilen >> 1);
  96. /*
  97. *   iplayer for send
  98. */
  99.     p->i.ident = intswap(nnipident++);
  100.     p->i.check = 0;
  101.     p->i.check = ipcheck((char *) &p->i, 10);
  102. /*
  103. *  send it
  104. */
  105.     return ((int) dlayersend((DLAYER *) p, sizeof(DLAYER) + sizeof(IPLAYER) + ilen));
  106. }
  107.  
  108.  
  109. /****************************************************************************/
  110. /*
  111. *   icmpinterpret ( p, icmplen )
  112. *
  113. * Interpret the icmp message that just came off the wire
  114. *
  115. */
  116. int 
  117. icmpinterpret(ICMPKT * p, int icmplen)
  118. {
  119.     uint            i;
  120.  
  121.     i = p->c.type;
  122.     
  123.     if (p->c.check)
  124.     {    /* ignore if chksum=0 */
  125.         if (ipcheck((char *) &p->c, icmplen >> 1))
  126.         {
  127.             netposterr(699);
  128.             return (0);
  129.         }
  130.     }
  131.     switch (i)
  132.     {
  133.     case 8:    /* ping request sent to me */
  134.         p->c.type = 0;    /* echo reply type */
  135.         neticmpturn(p, icmplen);    /* send back */
  136.         break;
  137.  
  138.     case 5:    /* ICMP redirect */
  139.         break;
  140.  
  141.     case 4:    /* ICMP source quench */
  142.         VPRINT("ICMP: source quench received");
  143.         OKpackets = 0;
  144.         SQwait += 100;
  145.         break;
  146.  
  147.     case 0:    /* ping reply ? */
  148.         break;
  149.  
  150.     case 3:    /* destination unreachable */
  151.         return -(630 + p->c.code);
  152.     default:
  153.         break;
  154.     }
  155.     netposterr(600 + i);    /* provide info for higher layer user */
  156.     return (0);
  157. }
  158.  
  159. /*
  160. *   iprecv ( )
  161. *
  162. *   Called by the udp layer to get next packet
  163. * validity of the packet (checksum, flags) and then passes it on to the
  164. * appropriate protocol handler.
  165. * Returns length of packet
  166. */
  167. unsigned char   junk[] = {0, 0, 0, 0};
  168.  
  169. int 
  170. iprecv(IPKT *p)                   /* ptr to packet from network */
  171. {
  172.     int             iplen,
  173.                     i;
  174.     int         retcode;
  175.  
  176.     retcode = ethrecv(p);
  177.     if (retcode == 0)
  178.         return 0;
  179.     if (retcode < 0)
  180.         return retcode;
  181. /*
  182. *  We cannot handle fragmented IP packets yet, return an error
  183. */
  184.     if (p->i.frags & 0x20)
  185.     {    /* check for a fragmented packet */
  186.         netposterr(304);
  187.         return (0);
  188.     }
  189. /*
  190. *  checksum verification of IP header
  191. */
  192.     if (p->i.check)
  193.     {    /* no IP checksumming if check=0 */
  194.         if (ipcheck(&p->i.versionandhdrlen, (p->i.versionandhdrlen & 0x0f) << 1))
  195.         {
  196.             netposterr(300);    /* bad IP checksum */
  197.             return (0);    /* drop packet */
  198.         }
  199.     }
  200. /*
  201. *  Extract total length of packet
  202. */
  203.     iplen = intswap(p->i.tlen);
  204. /*
  205. *  check to make sure that the packet is for me.
  206. *  Throws out all packets which are not directed to my IP address.
  207. */
  208.     /* n_printf("ip nnipnum %d.%d.%d.%d, dest %d.%d.%d.%d\n",
  209.             nnipnum[0], nnipnum[1],    nnipnum[2], nnipnum[3],
  210.             p->i.ipdest[0],
  211.             p->i.ipdest[1],
  212.             p->i.ipdest[2],
  213.             p->i.ipdest[3]);
  214.     */
  215.     if (memcmp(nnipnum, p->i.ipdest, 4)) /* not for me */
  216.     {    /* potential non-match */
  217.         if (!memcmp(nnipnum, junk, 4) && p->i.protocol == PROTUDP)
  218.         {
  219.             i = (p->i.versionandhdrlen & 0x0f) << 2;
  220.             return (iplen - i);
  221.         }
  222.         return (0);    /* drop packet */
  223.     }
  224. /*
  225. *  See if there are any IP options to be handled.
  226. *  We don't understand IP options, post a warning to the user and drop
  227. *  the packet.
  228. */
  229.     i = (p->i.versionandhdrlen & 0x0f) << 2;
  230.     if (i > 20)
  231.     {    /* check for options in packet */
  232.         netposterr(302);
  233.         return (0);
  234.     }
  235.     if (debug)
  236.     {
  237.         n_printf("Rx---->\n");
  238.         ipdump(p);
  239.     }
  240.     switch (p->i.protocol)
  241.     {    /* which protocol to handle this packet? */
  242.     case PROTUDP:
  243.         return (iplen - i);
  244.     case PROTICMP:
  245.         retcode = icmpinterpret((ICMPKT *) p, iplen - i);
  246.         return retcode;
  247.     default:
  248.         return (0);
  249.     }
  250. }
  251.  
  252.