home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / WATTCP / MSWATTCP.ZIP / SRC / PCICMP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-27  |  7.1 KB  |  312 lines

  1. /***
  2.  *
  3.  * File: pcicmp.c
  4.  *
  5.  * 27-Aug-93 fr
  6.  *    final cleanup
  7.  * 18-Jun-92 lr
  8.  *
  9.  * ICMP - RFC 792
  10.  *
  11.  */
  12.  
  13. #define WATTCP_KERNEL
  14. #define PCICMP
  15. #include <tcp.h>
  16.  
  17. /*********************** STATICS *************************/
  18.  
  19. static char *unreach[] = {
  20.     "Network Unreachable",
  21.     "Host Unreachable",
  22.     "Protocol Unreachable",
  23.     "Port Unreachable",
  24.     "Fragmentation needed and DF set",
  25.     "Source Route Failed" };
  26.     
  27. static char *exceed[] = {
  28.     "TTL exceeded in transit",
  29.     "Frag ReAsm time exceeded" };
  30.  
  31. static char *redirect[] = {
  32.     "Redirect for Network",
  33.     "Redirect for Host",
  34.     "Redirect for TOS and Network",
  35.     "Redirect for TOS and Host" };
  36.  
  37. /* constants */
  38.  
  39.  
  40. struct icmp_unused {
  41.     byte        type;
  42.     byte        code;
  43.     word        checksum;
  44.     longword    unused;
  45.     in_Header   ip;
  46.     byte        spares[ 8 ];
  47. };
  48.  
  49. struct icmp_pointer {
  50.     byte        type;
  51.     byte        code;
  52.     word        checksum;
  53.     byte        pointer;
  54.     byte        unused[ 3 ];
  55.     in_Header   ip;
  56. };
  57.  
  58. struct icmp_ip {
  59.     byte        type;
  60.     byte        code;
  61.     word        checksum;
  62.     longword    ipaddr;
  63.     in_Header   ip;
  64. };
  65.  
  66. struct icmp_echo {
  67.     byte        type;
  68.     byte        code;
  69.     word        checksum;
  70.     word        identifier;
  71.     word        sequence;
  72. };
  73.  
  74. struct icmp_timestamp {
  75.     byte        type;
  76.     byte        code;
  77.     word        checksum;
  78.     word        identifier;
  79.     word        sequence;
  80.     longword    original;       /* original timestamp */
  81.     longword    receive;        /* receive timestamp */
  82.     longword    transmit;       /* transmit timestamp */
  83. };
  84.  
  85. struct icmp_info {
  86.     byte        type;
  87.     byte        code;
  88.     word        checksum;
  89.     word        identifier;
  90.     word        sequence;
  91. };
  92.  
  93. typedef union  {
  94.     struct icmp_unused      unused;
  95.     struct icmp_pointer     pointer;
  96.     struct icmp_ip          ip;
  97.     struct icmp_echo        echo;
  98.     struct icmp_timestamp   timestamp;
  99.     struct icmp_info        info;
  100. } icmp_pkt;
  101.  
  102. struct _pkt {
  103.     in_Header   in;
  104.     icmp_pkt    icmp;
  105.     in_Header   data;
  106. };
  107.  
  108. static void icmp_print( icmp_pkt *icmp, char *msg);
  109. static void icmp_Reply( register struct _pkt *p,
  110.     longword src, longword dest, int icmp_length );
  111.  
  112. static word icmp_id = 0;
  113.  
  114. static longword ping_hcache = 0;        /* host */
  115. static longword ping_tcache = 0;        /* time */
  116. static longword ping_number = 0;
  117.  
  118. /*************************** END OF STATICS *****************/
  119. longword
  120. _chk_ping( longword host, longword *ptr )
  121. {
  122.     if ( ping_hcache == host ) {
  123.     ping_hcache = 0xffffffffL;
  124.     *ptr = ping_number;
  125.     return( ping_tcache );
  126.     }
  127.     return( 0xffffffffL );
  128. }
  129.  
  130.  
  131. static void
  132. icmp_print( icmp_pkt *icmp, char *msg)
  133. {
  134.     outs("\n\rICMP: ");
  135.     outs( msg );
  136. }
  137.  
  138. /*
  139.  *
  140.  */
  141. struct _pkt *
  142. icmp_Format( longword destip )
  143. {
  144.     eth_address dest;
  145.     /* char *temp; */
  146.  
  147.     /* we use arp rather than supplied hardware address */
  148.     /* after first ping this will still be in cache */
  149.  
  150.     if ( !_arp_resolve( destip , &dest ))
  151.     return( NULL );    /* unable to find address */
  152.     return( (struct _pkt*)_eth_formatpacket( &dest, 8 ));
  153. }
  154.  
  155. /*
  156.  * icmp_Reply - format a reply packet
  157.  *            - note that src and dest are NETWORK order not host!!!!
  158.  */
  159. static void
  160. icmp_Reply( register struct _pkt *p,
  161.     longword src, longword dest, int icmp_length )
  162. {
  163.     in_Header *ip;
  164.     icmp_pkt *icmp;
  165.  
  166.     ip = &p->in;
  167.     icmp = &p->icmp;
  168.  
  169.     /* finish the icmp checksum portion */
  170.     icmp->unused.checksum = 0;
  171.     icmp->unused.checksum = ~inchksum( icmp, icmp_length );
  172.  
  173.     /* encapsulate into a nice ip packet */
  174.     ip->ver = 4;
  175.     ip->hdrlen = 5;
  176.     ip->length = intel16( sizeof( in_Header ) + icmp_length);
  177.     ip->tos = 0;
  178.     ip->identification = intel16( icmp_id ++);  /* not using ip id */
  179.     ip->frag = 0;
  180.     ip->ttl = 250;
  181.     ip->proto = ICMP_PROTO;
  182.     ip->checksum = 0;
  183.     ip->source = src;
  184.     ip->destination = dest;
  185.     ip->checksum = ~ inchksum( ip, sizeof( in_Header ));
  186.  
  187.     _eth_send( intel16( ip->length ));
  188. }
  189.  
  190. void
  191. icmp_handler( in_Header *ip )
  192. {
  193.     register icmp_pkt *icmp, *newicmp;
  194.     struct _pkt *pkt;
  195.     int len, code;
  196.     in_Header *ret;
  197.     char buf[255];
  198.  
  199.     len = ip->hdrlen << 2;
  200.     icmp = (icmp_pkt*)((byte *)ip + len);
  201.     len = intel16( ip->length ) - len;
  202.     if ( inchksum( icmp, len ) != 0xffff ) {
  203.     outs("ICMP received with bad checksum\n\r");
  204.     return;
  205.     }
  206.  
  207.     code = icmp->unused.code;
  208.     switch ( icmp->unused.type) {
  209.     default:
  210.         icmp_print( icmp,"bad message");
  211.         break;
  212.     case 0 : /* icmp echo reply received */
  213.         icmp_print( icmp, "received icmp echo receipt");
  214.  
  215.         /* check if we were waiting for it */
  216.         ping_hcache = intel( ip->source );
  217.         ping_tcache = set_timeout( 1 ) - *(longword *)(&icmp->echo.identifier );
  218.         if (ping_tcache > 0xffffffffL)
  219.             ping_tcache += 0x1800b0L;
  220.         ping_number = *(longword*)( ((byte*)(&icmp->echo.identifier)) + 4 );
  221.         /* do more */
  222.         break;
  223.  
  224.     case 3 : /* destination unreachable message */
  225.         if (code < 6) {
  226.             icmp_print( icmp, unreach[ code ]);
  227.  
  228.             /* handle udp or tcp socket */
  229.             ret =(in_Header *)( (byte*)(icmp) + sizeof( icmp_pkt ));
  230.             if (ret->proto == TCP_PROTO)
  231.             _tcp_cancel( ret );
  232.             if (ret->proto == UDP_PROTO)
  233.             _udp_cancel( ret );
  234.         }
  235.         break;
  236.  
  237.     case 4  : /* source quench */
  238.         icmp_print( icmp, "Source Quench");
  239.         break;
  240.  
  241.     case 5  : /* redirect */
  242.         if (code < 4) {
  243.             _arp_register( intel( icmp->ip.ipaddr ),
  244.             intel( icmp->ip.ip.destination ));
  245.  
  246.             icmp_print( icmp, redirect[ code ]);
  247.             /* do it to some socket guy */
  248.         }
  249.         break;
  250.  
  251.     case 8  : /* icmp echo request */
  252.         if (print_icmp) {
  253.             fprintf(stderr,"PING request from : %s\n",
  254.             w_inet_ntoa( buf,intel(ip->source) ) );
  255.         }
  256.  
  257.         /* do arp and create packet */
  258. #ifdef OLD
  259.         if (!(pkt = icmp_Format( intel( ip->source ))))
  260.             break;
  261. #else /* !OLD */
  262.     /* format the packet with the request's hardware address */
  263.     pkt = (struct _pkt*)(_eth_formatpacket( _eth_hardware((byte *)ip), 8));
  264. #endif /* !OLD */
  265.         newicmp = &pkt->icmp;
  266.  
  267.         movmem( icmp, newicmp, len );
  268.         newicmp->echo.type = 0;
  269.         newicmp->echo.code = (byte)code;
  270.  
  271.         /* use supplied ip values in case we ever multi-home */
  272.         /* note that ip values are still in network order */
  273.         icmp_Reply( pkt,ip->destination, ip->source, len );
  274.         
  275.         if (print_icmp) {
  276.             fprintf(stderr,"PING reply sent to: %s\n\n",
  277.             w_inet_ntoa( buf,intel(ip->source) ) );
  278.         }
  279.         break;
  280.  
  281.     case 11 : /* time exceeded message */
  282.         if (code < 2 ) {
  283.             icmp_print( icmp, exceed[ code ]);
  284.         }
  285.         break;
  286.  
  287.     case 12 : /* parameter problem message */
  288.         icmp_print( icmp, "IP Parameter problem");
  289.         break;
  290.  
  291.     case 13 : /* timestamp message */
  292.         icmp_print( icmp, "Timestamp message");
  293.         /* send reply */
  294.         break;
  295.  
  296.     case 14 : /* timestamp reply */
  297.         icmp_print( icmp, "Timestamp reply");
  298.         /* should store */
  299.         break;
  300.  
  301.     case 15 : /* info request */
  302.         icmp_print( icmp,"Info requested");
  303.         /* send reply */
  304.         break;
  305.  
  306.     case 16 : /* info reply */
  307.         icmp_print( icmp,"Info reply");
  308.         break;
  309.  
  310.     }
  311. }
  312.