home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR3 / KA9Q212.ZIP / ICMP.C < prev    next >
C/C++ Source or Header  |  1993-07-16  |  7KB  |  270 lines

  1. /* Internet Control Message Protocol (ICMP)
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4.  
  5. /****************************************************************************
  6. *    $Id: icmp.c 1.2 93/07/16 11:45:21 ROOT_DOS Exp $
  7. *    14 Jun 93    1.2        GT    Fix warnings.                                    *
  8. ****************************************************************************/
  9.  
  10. #include <stdio.h>
  11. #include "global.h"
  12. #include "mbuf.h"
  13. #include "iface.h"
  14. #include "ip.h"
  15. #include "icmp.h"
  16. #include "netuser.h"
  17.  
  18. struct mib_entry Icmp_mib[] = {
  19.     { "",            0 },
  20.     { "icmpInMsgs",        0 },
  21.     { "icmpInErrors",        0 },
  22.     { "icmpInDestUnreachs",    0 },
  23.     { "icmpInTimeExcds",    0 },
  24.     { "icmpInParmProbs",    0 },
  25.     { "icmpInSrcQuenchs",    0 },
  26.     { "icmpInRedirects",    0 },
  27.     { "icmpInEchos",        0 },
  28.     { "icmpInEchoReps",    0 },
  29.     { "icmpInTimestamps",    0 },
  30.     { "icmpInTimestampReps",    0 },
  31.     { "icmpInAddrMasks",    0 },
  32.     { "icmpInAddrMaskReps",    0 },
  33.     { "icmpOutMsgs",        0 },
  34.     { "icmpOutErrors",    0 },
  35.     { "icmpOutDestUnreachs",    0 },
  36.     { "icmpOutTimeExcds",    0 },
  37.     { "icmpOutParmProbs",    0 },
  38.     { "icmpOutSrcQuenchs",    0 },
  39.     { "icmpOutRedirects",    0 },
  40.     { "icmpOutEchos",        0 },
  41.     { "icmpOutEchoReps",    0 },
  42.     { "icmpOutTimestamps",    0 },
  43.     { "icmpOutTimestampReps",    0 },
  44.     { "icmpOutAddrMasks",    0 },
  45.     { "icmpOutAddrMaskReps",    0 },
  46. };
  47.  
  48. /* Process an incoming ICMP packet */
  49. void
  50. icmp_input(iface,ip,bp,rxbroadcast)
  51. struct iface *iface;    /* Incoming interface (ignored) */
  52. struct ip *ip;        /* Pointer to decoded IP header structure */
  53. struct mbuf *bp;    /* Pointer to ICMP message */
  54. int rxbroadcast;
  55. {
  56.     struct icmplink *ipp;
  57.     struct mbuf *tbp;
  58.     struct icmp icmp;    /* ICMP header */
  59.     struct ip oip;        /* Offending datagram header */
  60.     int16 type;        /* Type of ICMP message */
  61.     int16 length;
  62.  
  63.     icmpInMsgs++;
  64.     if(rxbroadcast){
  65.         /* Broadcast ICMP packets are to be IGNORED !! */
  66.         icmpInErrors++;
  67.         free_p(bp);
  68.         return;
  69.     }
  70.     length = ip->length - IPLEN - ip->optlen;
  71.     if(cksum(NULLHEADER,bp,length) != 0){
  72.         /* Bad ICMP checksum; discard */
  73.         icmpInErrors++;
  74.         free_p(bp);
  75.         return;
  76.     }
  77.     ntohicmp(&icmp,&bp);
  78.  
  79.     /* Process the message. Some messages are passed up to the protocol
  80.      * module for handling, others are handled here.
  81.      */
  82.     type = icmp.type;
  83.     
  84.     switch(uchar(type)){
  85.     case ICMP_TIME_EXCEED:    /* Time-to-live Exceeded */
  86.     case ICMP_DEST_UNREACH:    /* Destination Unreachable */
  87.     case ICMP_QUENCH:    /* Source Quench */
  88.         switch(uchar(type)){
  89.         case ICMP_TIME_EXCEED:    /* Time-to-live Exceeded */
  90.             icmpInTimeExcds++;
  91.             break;
  92.         case ICMP_DEST_UNREACH:    /* Destination Unreachable */
  93.             icmpInDestUnreachs++;
  94.             break;
  95.         case ICMP_QUENCH:    /* Source Quench */
  96.             icmpInSrcQuenchs++;
  97.             break;
  98.         }
  99.         ntohip(&oip,&bp);    /* Extract offending IP header */
  100.         if(Icmp_trace){
  101.             printf("ICMP from %s:",inet_ntoa(ip->source));
  102.             printf(" dest %s %s",inet_ntoa(oip.dest),
  103.              smsg(Icmptypes,ICMP_TYPES,uchar(type)));
  104.             switch(uchar(type)){
  105.             case ICMP_TIME_EXCEED:
  106.                 printf(" %s\n",
  107.                  smsg(Exceed,NEXCEED,uchar(icmp.code)));
  108.                 break;
  109.             case ICMP_DEST_UNREACH:
  110.                 printf(" %s\n",
  111.                  smsg(Unreach,NUNREACH,uchar(icmp.code)));
  112.                 break;
  113.             default:
  114.                 printf(" %u\n",uchar(icmp.code));
  115.                 break;
  116.             }
  117.         }
  118.         for(ipp = Icmplink;ipp->funct != NULL;ipp++)
  119.             if(ipp->proto == oip.protocol)
  120.                 break;
  121.         if(ipp->funct != NULL){
  122.             (*ipp->funct)(ip->source,oip.source,oip.dest,icmp.type,
  123.              icmp.code,&bp);
  124.         }
  125.         break;
  126.     case ICMP_ECHO:        /* Echo Request */
  127.         /* Change type to ECHO_REPLY, recompute checksum,
  128.          * and return datagram.
  129.          */
  130.         icmpInEchos++;
  131.         icmp.type = ICMP_ECHO_REPLY;
  132.         if((tbp = htonicmp(&icmp,bp)) == NULLBUF){
  133.             free_p(bp);
  134.             return;
  135.         }
  136.         icmpOutEchoReps++;
  137.         ip_send(ip->dest,ip->source,ICMP_PTCL,ip->tos,0,tbp,length,0,0);
  138.         return;
  139.     case ICMP_REDIRECT:    /* Redirect */
  140.         icmpInRedirects++;
  141.         break;
  142.     case ICMP_PARAM_PROB:    /* Parameter Problem */
  143.         icmpInParmProbs++;
  144.         break;
  145.     case ICMP_ECHO_REPLY:    /* Echo Reply */
  146.         icmpInEchoReps++;
  147.         echo_proc(ip->source,ip->dest,&icmp,bp);
  148.         bp = NULLBUF;    /* so it won't get freed */
  149.         break;
  150.     case ICMP_TIMESTAMP:    /* Timestamp */
  151.         icmpInTimestamps++;
  152.         break;
  153.     case ICMP_TIME_REPLY:    /* Timestamp Reply */
  154.         icmpInTimestampReps++;
  155.         break;
  156.     case ICMP_INFO_RQST:    /* Information Request */
  157.         break;
  158.     case ICMP_INFO_REPLY:    /* Information Reply */
  159.         break;
  160.     }
  161.     free_p(bp);
  162. }
  163. /* Return an ICMP response to the sender of a datagram.
  164.  * Unlike most routines, the callER frees the mbuf.
  165.  */
  166. int
  167. icmp_output(ip,data,type,code,args)
  168. struct ip *ip;        /* Header of offending datagram */
  169. struct mbuf *data;    /* Data portion of datagram */
  170. char type,code;        /* Codes to send */
  171. union icmp_args *args;
  172. {
  173.     struct mbuf *bp = NULLBUF;
  174.     struct icmp icmp;    /* ICMP protocol header */
  175.     int16 dlen;        /* Length of data portion of offending pkt */
  176.     int16 length;        /* Total length of reply */
  177.  
  178.     if(ip == NULLIP)
  179.         return -1;
  180.     if(uchar(ip->protocol) == ICMP_PTCL){
  181.         /* Peek at type field of ICMP header to see if it's safe to
  182.          * return an ICMP message
  183.          */
  184.         switch(uchar(data->data[0])){
  185.         case ICMP_ECHO_REPLY:
  186.         case ICMP_ECHO:
  187.         case ICMP_TIMESTAMP:
  188.         case ICMP_TIME_REPLY:
  189.         case ICMP_INFO_RQST:
  190.         case ICMP_INFO_REPLY:
  191.             break;    /* These are all safe */
  192.         default:
  193.             /* Never send an ICMP error message about another
  194.              * ICMP error message!
  195.              */
  196.             return -1;
  197.         }
  198.     }
  199.     /* Compute amount of original datagram to return.
  200.      * We return the original IP header, and up to 8 bytes past that.
  201.      */
  202.     dlen = min(8,len_p(data));
  203.     length = dlen + ICMPLEN + IPLEN + ip->optlen;
  204.     /* Take excerpt from data portion */
  205.     if(data != NULLBUF && dup_p(&bp,data,0,dlen) == 0)
  206.         return -1;    /* The caller will free data */
  207.  
  208.     /* Recreate and tack on offending IP header */
  209.     if((data = htonip(ip,bp,IP_CS_NEW)) == NULLBUF){
  210.         free_p(bp);
  211.         icmpOutErrors++;
  212.         return -1;
  213.     }
  214.     icmp.type = type;
  215.     icmp.code = code;
  216.     icmp.args.unused = 0;
  217.     switch(uchar(icmp.type)){
  218.     case ICMP_PARAM_PROB:
  219.         icmpOutParmProbs++;
  220.         icmp.args.pointer = args->pointer;
  221.         break;
  222.     case ICMP_REDIRECT:
  223.         icmpOutRedirects++;
  224.         icmp.args.address = args->address;
  225.         break;
  226.     case ICMP_ECHO:
  227.         icmpOutEchos++;
  228.         break;
  229.     case ICMP_ECHO_REPLY:
  230.         icmpOutEchoReps++;
  231.         break;
  232.     case ICMP_INFO_RQST:
  233.         break;
  234.     case ICMP_INFO_REPLY:
  235.         break;
  236.     case ICMP_TIMESTAMP:
  237.         icmpOutTimestamps++;
  238.         break;
  239.     case ICMP_TIME_REPLY:
  240.         icmpOutTimestampReps++;
  241.         icmp.args.echo.id = args->echo.id;
  242.         icmp.args.echo.seq = args->echo.seq;
  243.         break;
  244.     case ICMP_ADDR_MASK:
  245.         icmpOutAddrMasks++;
  246.         break;
  247.     case ICMP_ADDR_MASK_REPLY:
  248.         icmpOutAddrMaskReps++;
  249.         break;
  250.     case ICMP_DEST_UNREACH:
  251.         if(icmp.code == ICMP_FRAG_NEEDED)
  252.             icmp.args.mtu = args->mtu;
  253.         icmpOutDestUnreachs++;
  254.         break;
  255.     case ICMP_TIME_EXCEED:
  256.         icmpOutTimeExcds++;
  257.         break;
  258.     case ICMP_QUENCH:
  259.         icmpOutSrcQuenchs++;
  260.         break;
  261.     }
  262.     icmpOutMsgs++;
  263.     /* Now stick on the ICMP header */
  264.     if((bp = htonicmp(&icmp,data)) == NULLBUF){
  265.         free_p(data);
  266.         return -1;
  267.     }
  268.     return ip_send(INADDR_ANY,ip->source,ICMP_PTCL,ip->tos,0,bp,length,0,0);
  269. }
  270.