PCICMP.C
上传用户:better800
上传日期:2022-06-13
资源大小:1853k
文件大小:8k
源码类别:

TCP/IP协议栈

开发平台:

DOS

  1. #include <copyright.h>
  2. #include <wattcp.h>
  3. #include <mem.h>
  4. #include <dos.h>
  5. /*
  6.  * ICMP - RFC 792 & 1122
  7.  */
  8. static char *unreach[] = {
  9. "Network Unreachable",
  10. "Host Unreachable",
  11. "Protocol Unreachable",
  12. "Port Unreachable",
  13. // R. Whitby
  14. "Fragmentation Needed and DF set",
  15. "Source Route Failed",
  16. "Destination Network Unknown",
  17. "Destination Host Unknown",
  18. "Source Host Isolated",
  19. "Destination Network Prohibited",
  20. "Destination Host Prohibited",
  21. "Network TOS Unreachable",
  22. "Host TOS Unreachable" };
  23. static char *exceed[] = {
  24. // R. Whitby
  25. "TTL Exceeded in Transit",
  26. "Fragment Reassembly Time Exceeded" };
  27. static char *redirect[] = {
  28. "Redirect for Network",
  29. "Redirect for Host",
  30. "Redirect for TOS and Network",
  31. "Redirect for TOS and Host" };
  32. /* constants */
  33. #include <icmp.h>
  34. // R. Whitby
  35. extern void (*_dbugxmit)( sock_type *s, in_Header *inp, void *phdr,
  36.      unsigned line );
  37. extern void (*_dbugrecv)( sock_type *s, in_Header *inp, void *phdr,
  38.      unsigned line );
  39. static word icmp_id = 0;
  40. static longword ping_hcache = 0; /* host */
  41. static longword ping_tcache = 0; /* time */
  42. static longword ping_number = 0;
  43. extern word multihomes;
  44. /* handler called in icmp_handler if this isn't null */
  45. static icmp_handler_type user_icmp_handler = NULL;
  46. longword _chk_ping( longword host, longword *ptr )
  47. {
  48.     if ( ping_hcache == host ) {
  49. ping_hcache = 0xffffffffL;
  50. *ptr = ping_number;
  51. return( ping_tcache );
  52.     }
  53.     return( 0xffffffffL );
  54. }
  55. static void icmp_print( icmp_pkt *icmp, char *msg )
  56. {
  57. icmp=icmp;     // get rid of warning
  58. //    outs("nrICMP: ");
  59. //    outs( msg );
  60. //    outs("nr");
  61. }
  62. #ifdef NOTUSED // R. Whitby
  63. /*
  64.  *
  65.  */
  66. static struct _pkt *icmp_Format( longword destip )
  67. {
  68.     eth_address dest;
  69. /*    char *temp; */
  70.     /* we use arp rather than supplied hardware address */
  71.     /* after first ping this will still be in cache */
  72.     if ( !_arp_resolve( destip , &dest, 0 ))
  73. return( NULL ); /* unable to find address */
  74.     return( (struct _pkt*)_eth_formatpacket( &dest, 8 ));    /* &dest okay? */
  75. }
  76. #endif  // R. Whitby
  77. /*
  78.  * icmp_Reply - format and send a reply packet
  79.  *         - note that src and dest are NETWORK order not host!!!!
  80.  */
  81. static void icmp_Reply( struct _pkt *p, longword src, longword dest, int icmp_length )
  82. {
  83.     in_Header *ip;
  84.     icmp_pkt *icmp;
  85.     ip = &p->in;
  86.     memset( ip, 0, sizeof( in_Header ));
  87.     icmp = &p->icmp;
  88.     /* finish the icmp checksum portion */
  89.     icmp->unused.checksum = 0;
  90.     icmp->unused.checksum = ~checksum( icmp, icmp_length );
  91.     /* encapsulate into a nice ip packet */
  92.     ip->ver = 4;
  93.     ip->hdrlen = 5;
  94.     ip->length = intel16( sizeof( in_Header ) + icmp_length);
  95.     ip->tos = 0;
  96.     ip->identification = intel16( icmp_id ++); /* not using ip id */
  97. //    ip->frag = 0;
  98.     ip->ttl = 250;
  99.     ip->proto = ICMP_PROTO;
  100.     ip->checksum = 0;
  101.     ip->source = src;
  102.     ip->destination = dest;
  103.     ip->checksum = ~ checksum( ip, sizeof( in_Header ));
  104.     if (_dbugxmit) (*_dbugxmit)( NULL, ip, icmp, 0); // R. Whitby
  105.     _eth_send( intel16( ip->length ));
  106. }
  107. // S. Lawson - send ICMP port unreachable
  108. void icmp_Unreach(in_Header *ip) {
  109.     icmp_pkt *icmp;
  110.     struct _pkt *pkt;
  111.     word len;
  112.     len = in_GetHdrlenBytes(ip)+8;
  113.     pkt = (struct _pkt*)(_eth_formatpacket( _eth_hardware((byte*)ip), 8));
  114.     icmp = &pkt->icmp;
  115.     icmp->unused.type = ICMPTYPE_UNREACHABLE;
  116.     icmp->unused.code = ICMP_UNREACH_PORT;
  117.     icmp->unused.unused = 0L;
  118.     movmem(ip, &icmp->unused.ip, len);
  119.     icmp_Reply( pkt,ip->destination, ip->source, 8+len );
  120. }
  121. // S. Lawson - BC 2.0 doesn't have the underscore variety
  122. #ifndef _disable
  123. #define _disable disable
  124. #define _enable enable
  125. #endif
  126. /*
  127.  * Register the user ICMP handler.  Only one at a time...
  128.  * To disable user handler, call  set_icmp_handler(NULL);
  129.  */
  130. void set_icmp_handler( icmp_handler_type user_handler )
  131. {
  132.    _disable();
  133.    user_icmp_handler = user_handler;
  134.    _enable();
  135. }
  136. int icmp_handler( in_Header *ip )
  137. {
  138.     icmp_pkt *icmp, *newicmp;
  139.     struct _pkt *pkt;
  140.     int len, code;
  141.     in_Header *ret;
  142.     len = in_GetHdrlenBytes( ip );
  143.     icmp = (icmp_pkt*)((byte *)ip + len);
  144.     if (_dbugrecv) (*_dbugrecv)( NULL, ip, icmp, 0); // R. Whitby
  145.     len = intel16( ip->length ) - len;
  146.     if ( checksum( icmp, len ) != 0xffff ) {
  147. // R. Whitby outs("ICMP received with bad checksumnr");
  148. if (debug_on > 0) icmp_print(icmp, "Bad Checksum");  // R. Whitby
  149. return( 1 );
  150.     }
  151.    /*
  152.     * If there's a user handler installed, call the user's handler;
  153.     *     return of anything but 0 and this handler will continue
  154.     *     processing the message after the user is done with it.
  155.     * Otherwise, stop processing it now.
  156.     */
  157.     if( user_icmp_handler )
  158.     {
  159. if( (user_icmp_handler)( ip ) == 0 )   /* don't continue processing? */
  160. return( 1 );
  161.     }
  162.     code = icmp->unused.code;
  163.     ret = & (icmp->ip.ip);
  164.     switch ( icmp->unused.type) {
  165. case 0 : /* icmp echo reply received */
  166. /* icmp_print( icmp, "received icmp echo receipt"); */
  167. if (debug_on > 0) icmp_print( icmp, "Echo Reply");  // R. Whitby
  168. /* check if we were waiting for it */
  169. ping_hcache = intel( ip->source );
  170. ping_tcache = set_timeout( 1 ) - *(longword *)(&icmp->echo.identifier );
  171. if (ping_tcache > 0xffffffffL)
  172.     ping_tcache += 0x1800b0L;
  173. ping_number = *(longword*)( ((byte*)(&icmp->echo.identifier)) + 4 );
  174. /* do more */
  175. break;
  176. case 3 : /* destination unreachable message */
  177. // R. Whitby if (code < 6) {
  178. if (code < 13) {  // R. Whitby
  179.     icmp_print( icmp, unreach[ code ]);
  180.     /* handle udp or tcp socket */
  181.     if (ret->proto == TCP_PROTO)
  182. _tcp_cancel( ret, 1, unreach[ code ], 0 );
  183.     if (ret->proto == UDP_PROTO)
  184. _udp_cancel( ret );
  185. }
  186. break;
  187. case 4  : /* source quench */
  188. if (debug_on > 0 ) icmp_print( icmp, "Source Quench");
  189. if (ret->proto == TCP_PROTO)
  190.     _tcp_cancel( ret, 2, NULL, 0 );
  191. break;
  192. case 5  : /* redirect */
  193. if (code < 4) {
  194.     if (ret->proto == TCP_PROTO)
  195. /* do it to some socket guy */
  196. _tcp_cancel( ret, 5, NULL, icmp->ip.ipaddr );
  197.     if (debug_on > 0 ) icmp_print( icmp, redirect[ code ]);
  198. }
  199. break;
  200. case 8  : /* icmp echo request */
  201. /* icmp_print( icmp, "PING requested of us"); */
  202. if (debug_on > 0) icmp_print( icmp, "Echo Request"); // R. Whitby
  203. // don't reply if the request was made by ourselves
  204. // such as a problem with Etherslip pktdrvr
  205.                 if  ( (longword) (intel(ip->destination) - my_ip_addr) > multihomes )
  206.     return( 1 );
  207. // do arp and create packet
  208. /* format the packet with the request's hardware address */
  209. pkt = (struct _pkt*)(_eth_formatpacket( _eth_hardware((byte*)ip), 8));
  210. newicmp = &pkt->icmp;
  211. movmem( icmp, newicmp, len );
  212. newicmp->echo.type = 0;
  213. newicmp->echo.code = code;
  214. /* use supplied ip values in case we ever multi-home */
  215. /* note that ip values are still in network order */
  216. icmp_Reply( pkt,ip->destination, ip->source, len );
  217. /* icmp_print( newicmp, "PING reply sent"); */
  218. break;
  219. case 11 : /* time exceeded message */
  220. if (code < 2 ) {
  221.     icmp_print( icmp, exceed[ code ]);
  222.     if ((ret->proto == TCP_PROTO) && (code != 1))
  223. _tcp_cancel( ret, 1, NULL, 0 );
  224. }
  225. break;
  226. case 12 : /* parameter problem message */
  227. icmp_print( icmp, "IP Parameter Problem");
  228. break;
  229. // R. Whitby - added debug_on test to remaining cases
  230. case 13 : /* timestamp message */
  231. if (debug_on > 0) icmp_print( icmp, "Timestamp Request");
  232. /* send reply */
  233. break;
  234. case 14 : /* timestamp reply */
  235. if (debug_on > 0) icmp_print( icmp, "Timestamp Reply");
  236. /* should store */
  237. break;
  238. case 15 : /* info request */
  239. if (debug_on > 0) icmp_print( icmp,"Info Request");
  240. /* send reply */
  241. break;
  242. case 16 : /* info reply */
  243. if (debug_on > 0) icmp_print( icmp,"Info Reply");
  244. break;
  245. // R. Whitby
  246. default : /* unknown */
  247. if (debug_on > 0) icmp_print( icmp,"Unknown Type");
  248. break;
  249.     }
  250.     return( 1 );
  251. }