home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / WATTCP / UNZIPPED / WNWATTCP / SRC / PCICMP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-20  |  6.6 KB  |  292 lines

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