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

TCP/IP协议栈

开发平台:

DOS

  1. /*
  2.  * Address Resolution Protocol
  3.  *
  4.  *  Externals:
  5.  *  _arp_handler( pb ) - returns 1 on handled correctly, 0 on problems
  6.  *  _arp_resolve - rets 1 on success, 0 on fail
  7.  *               - does not return hardware address if passed NULL for buffer
  8.  *
  9.  */
  10. #include <copyright.h>
  11. #include <wattcp.h>
  12. #include <string.h>
  13. #include <mem.h>
  14. #define MAX_ARP_DATA 40
  15. #define MAX_ARP_ALIVE  300 /* five minutes */
  16. #define MAX_ARP_GRACE  100 /* additional grace upon expiration */
  17. extern word wathndlcbrk;
  18. extern word watcbroke;
  19. extern word multihomes;
  20. typedef struct {
  21.     longword ip;
  22.     eth_address hardware;
  23.     byte flags;
  24.     byte bits; /* bits in network */
  25.     longword expiry;
  26. } arp_tables;
  27. typedef struct {
  28.     longword gate_ip;
  29.     longword subnet;
  30.     longword mask;
  31. } gate_tables;
  32. #define ARP_FLAG_NEED 0
  33. #define ARP_FLAG_FOUND  1
  34. #define ARP_FLAG_FIXED  255 /* cannot be removed */
  35. /*
  36.  * arp resolution cache - we zero fill it to save an initialization routine
  37.  */
  38. static arp_tables arp_data[ MAX_ARP_DATA ] =
  39.  { {0uL,{{0,0,0,0,0,0}},0,0,0uL}, {0uL,{{0,0,0,0,0,0}},0,0,0uL}, {0uL,{{0,0,0,0,0,0}},0,0,0uL},
  40.    {0uL,{{0,0,0,0,0,0}},0,0,0uL}, {0uL,{{0,0,0,0,0,0}},0,0,0uL}, {0uL,{{0,0,0,0,0,0}},0,0,0uL},
  41.    {0uL,{{0,0,0,0,0,0}},0,0,0uL}, {0uL,{{0,0,0,0,0,0}},0,0,0uL}, {0uL,{{0,0,0,0,0,0}},0,0,0uL},
  42.    {0uL,{{0,0,0,0,0,0}},0,0,0uL}, {0uL,{{0,0,0,0,0,0}},0,0,0uL}, {0uL,{{0,0,0,0,0,0}},0,0,0uL},
  43.    {0uL,{{0,0,0,0,0,0}},0,0,0uL}, {0uL,{{0,0,0,0,0,0}},0,0,0uL}, {0uL,{{0,0,0,0,0,0}},0,0,0uL},
  44.    {0uL,{{0,0,0,0,0,0}},0,0,0uL}, {0uL,{{0,0,0,0,0,0}},0,0,0uL}, {0uL,{{0,0,0,0,0,0}},0,0,0uL},
  45.    {0uL,{{0,0,0,0,0,0}},0,0,0uL}, {0uL,{{0,0,0,0,0,0}},0,0,0uL}};
  46. gate_tables _arp_gate_data[ MAX_GATE_DATA ];
  47. word _arp_last_gateway;
  48. extern void (*system_yield)();      /* from pctcp.c 2000.4.14 EE */
  49. /*
  50.  * _arp_add_gateway - if data is NULL, don't use string
  51.  */
  52. void _arp_add_gateway( char *data, longword ip )
  53. {
  54.     int i;
  55.     char *subnetp, *maskp;
  56.     longword subnet, mask;
  57.     subnet = mask = 0;
  58.     if ( data ) {
  59. maskp = NULL;
  60. if ( (subnetp = strchr( data, ',' )) != NULL ) {
  61.     *subnetp++ = 0;
  62.     if ( (maskp = strchr( subnetp, ',' )) != NULL ) {
  63. *maskp++ = 0;
  64. mask = aton( maskp );
  65. subnet = aton( subnetp );
  66.     } else {
  67. subnet = aton( subnetp );
  68. switch ( subnet >> 30 ) {
  69.     case 0 :
  70.     case 1 : mask = 0xff000000L; break;
  71.     case 2 : mask = 0xfffffe00L; break; /* minimal class b */
  72.     case 3 : mask = 0xffffff00L; break;
  73. }
  74.     }
  75. }
  76.         ip = aton( data );
  77.     }
  78.     if ( _arp_last_gateway < MAX_GATE_DATA ) {
  79.         for ( i = 0 ; i < _arp_last_gateway ; ++i ) {
  80.             if ( _arp_gate_data[i].mask < mask ) {
  81.                 movmem( &_arp_gate_data[i], &_arp_gate_data[i+1],
  82.                     (_arp_last_gateway - i) * sizeof( gate_tables ));
  83.                 break;
  84.             }
  85.         }
  86.         _arp_gate_data[i].gate_ip = ip;
  87.         _arp_gate_data[i].subnet = subnet;
  88.         _arp_gate_data[i].mask = mask;
  89.         ++_arp_last_gateway;    /* used up another one */
  90.     }
  91. }
  92. static void _arp_request( longword ip )
  93. {
  94.     arp_Header *op;
  95.     op = (arp_Header *)_eth_formatpacket(&_eth_brdcast, 0x608);
  96.     op->hwType = arp_TypeEther;
  97.     op->protType = 0x008; /* IP */
  98.     op->hwProtAddrLen = sizeof(eth_address) + (sizeof(longword)<<8);
  99.     op->opcode = ARP_REQUEST;
  100.     op->srcIPAddr = intel( my_ip_addr );
  101.     movmem(&_eth_addr, &op->srcEthAddr, sizeof(eth_address));
  102.     op->dstIPAddr = intel( ip );
  103.     /* ...and send the packet */
  104.     _eth_send( sizeof(arp_Header) );
  105. }
  106. static word arp_index = 0; /* rotates round-robin */
  107. static arp_tables *_arp_search( longword ip, int create )
  108. {
  109.     int i;
  110.     arp_tables *arp_ptr;
  111.     for ( i = 0; i < MAX_ARP_DATA; ++i ) {
  112. if ( ip == arp_data[i].ip )
  113.     return( &arp_data[i] );
  114.     }
  115.     /* didn't find any */
  116.     if ( create ) {
  117. /* pick an old or empty one */
  118. for ( i = 0; i < MAX_ARP_DATA ; ++i ) {
  119.     arp_ptr = &arp_data[i];
  120.     if ( ! arp_ptr->ip || chk_timeout(arp_ptr->expiry+MAX_ARP_GRACE))
  121. return( arp_ptr );
  122. }
  123. /* pick one at pseudo-random */
  124. return( &arp_data[ arp_index = ( arp_index + 1 ) % MAX_ARP_DATA ] );
  125.     }
  126.     return( NULL );
  127. }
  128. void _arp_register( longword use, longword instead_of )
  129. {
  130. /*    word i; */
  131.     arp_tables *arp_ptr;
  132.     if ( (arp_ptr = _arp_search( instead_of, 0 )) != NULL) {
  133. /* now insert the address of the new guy */
  134. arp_ptr->flags = ARP_FLAG_NEED;
  135.         _arp_resolve( use, &arp_ptr->hardware, 0);
  136. arp_ptr->expiry = set_timeout( MAX_ARP_ALIVE );
  137. return;
  138.     }
  139.     arp_ptr = _arp_search( use , 1 ); /* create a new one */
  140.     arp_ptr->flags = ARP_FLAG_NEED;
  141. /* but now is this right?  if 'use' was already in the arp cache,
  142.      we're now nuking it... at worst an efficiency problem */
  143.     arp_ptr->ip = instead_of;  /* use; */               /* 94.11.30 */
  144.     _arp_resolve( use, &arp_ptr->hardware, 0);
  145.     arp_ptr->expiry = set_timeout( MAX_ARP_ALIVE );
  146. }
  147. void _arp_tick( longword ip )
  148. {
  149.     arp_tables *arp_ptr;
  150.     if ( (arp_ptr = _arp_search( ip , 0)) != NULL )
  151. arp_ptr->expiry = set_timeout( MAX_ARP_ALIVE );
  152. }
  153. /*
  154.  * _arp_handler - handle incomming ARP packets
  155.  */
  156. int _arp_handler( arp_Header *in)
  157. {
  158.     arp_Header *op;
  159.     longword his_ip;
  160.     arp_tables *arp_ptr;
  161.     if ( in->hwType != arp_TypeEther ||      /* have ethernet hardware, */
  162. in->protType != 8 )           /* and internet software, */
  163. return( 0 );
  164.     /* continuously accept data - but only for people we talk to */
  165.     his_ip = intel( in->srcIPAddr );
  166.     if ( (arp_ptr = _arp_search( his_ip, 0)) != NULL ) {
  167. arp_ptr->expiry = set_timeout( MAX_ARP_ALIVE );
  168. movmem( &in->srcEthAddr, &arp_ptr->hardware, sizeof( eth_address ));
  169. arp_ptr->flags = ARP_FLAG_FOUND;
  170.     }
  171.     /* does someone else want our Ethernet address ? */
  172.     if ( in->opcode == ARP_REQUEST &&        /* and be a resolution req. */
  173.  ((longword)(intel(in->dstIPAddr) - my_ip_addr ) <= multihomes )
  174.        )  {
  175. op = (arp_Header *)_eth_formatpacket(&in->srcEthAddr, 0x0608);
  176. op->hwType = arp_TypeEther;
  177. op->protType = 0x008; /* intel for ip */
  178. op->hwProtAddrLen = sizeof(eth_address) + (sizeof(longword) << 8 );
  179. op->opcode = ARP_REPLY;
  180. op->dstIPAddr = in->srcIPAddr;
  181. op->srcIPAddr = in->dstIPAddr;
  182. movmem(&_eth_addr, &op->srcEthAddr, sizeof(eth_address));
  183. movmem(&in->srcEthAddr, &op->dstEthAddr, sizeof(eth_address));
  184. _eth_send(sizeof(arp_Header));
  185. return ( 1 );
  186.     }
  187.     return( 1 );
  188. }
  189. /*
  190.  * _arp_resolve - resolve IP address to hardware address
  191.  */
  192. int _arp_resolve( longword ina, eth_address *ethap, int nowait )
  193. {
  194.     static arp_tables *arp_ptr;
  195.     int i, oldhndlcbrk;
  196.     longword timeout, resend;
  197.     
  198.    
  199. /*    int packettype; */
  200.     if ( _pktdevclass == PD_SLIP ) {
  201. /* we are running slip or somthing which does not use addresses */
  202. return( 1 );
  203.     }
  204.     if ( (longword)(ina - my_ip_addr) < multihomes) {
  205. if (ethap)
  206.     movmem( &_eth_addr, ethap, sizeof( eth_address ));
  207. return( 1 );
  208.     }
  209.     /* attempt to solve with ARP cache */
  210.     /* fake while loop */
  211.     while ( (arp_ptr = _arp_search( ina, 0)) != NULL ) {
  212. if ( arp_ptr->flags != ARP_FLAG_NEED ) {
  213.     /* has been resolved */
  214. #ifdef NEW_EXPIRY
  215.     if ( chk_timeout( arp_ptr->timeout ) {
  216. if ( ! chk_timeout( arp_ptr->timeout + MAX_ARP_GRACE ) {
  217.     /* we wish to refresh it asynchronously */
  218.     _arp_request( ina );
  219. else
  220.     break; /* must do full fledged arp */
  221. #endif NEW_EXPIRY
  222.     if (ethap)
  223. movmem( &arp_ptr->hardware, ethap, sizeof(eth_address));
  224.     return( 1 );
  225. }
  226.         break;
  227.     }
  228.     /* make a new one if necessary */
  229.     if (! arp_ptr )
  230. arp_ptr = _arp_search( ina, 1 );
  231.     /* we must look elsewhere - but is it on our subnet??? */
  232.     if (( ina ^ my_ip_addr ) & sin_mask ) {
  233. /* not of this network */
  234. for ( i = 0; i < _arp_last_gateway ; ++i ) {
  235.             //  is the gateway on our subnet
  236.             //  or if mask is ff...ff, we assume any gateway must succeed
  237.             //  because we are on 'no' network
  238.             if ((((_arp_gate_data[i].gate_ip ^ my_ip_addr ) & sin_mask ) == 0)
  239.              || ( sin_mask == 0xffffffffL )) {
  240.                 /* compare the various subnet bits */
  241.                 if ( (_arp_gate_data[i].mask & ina ) == _arp_gate_data[i].subnet ) {
  242.                     if ( _arp_resolve( _arp_gate_data[i].gate_ip , ethap, nowait ))
  243.                         return( 1 );
  244.                 }
  245.     }
  246. }
  247.         return( 0 );
  248.     }
  249.     /* return if no host, or no gateway */
  250.     if (! ina )
  251. return( 0 );
  252.     /* is on our subnet, we must resolve */
  253.     timeout = set_timeout( 5 ); /* five seconds is long for ARP */
  254.     oldhndlcbrk = wathndlcbrk;
  255.     wathndlcbrk = 1;
  256.     watcbroke = 0;
  257.      
  258.     while ( !chk_timeout( timeout )) {
  259. /* do the request */
  260. _arp_request( arp_ptr->ip = ina );              
  261. resend = set_timeout( 1 ) - 14L; /* 250 ms */
  262. while (!chk_timeout( resend )) {
  263.     
  264.             if (watcbroke) 
  265.              goto fail;
  266.     tcp_tick( NULL );
  267.     if ( arp_ptr->flags) {
  268. if (ethap)
  269.     movmem( &arp_ptr->hardware, ethap, sizeof(eth_address));
  270. arp_ptr->expiry = set_timeout( MAX_ARP_ALIVE );
  271.                 watcbroke = 0;
  272.                 wathndlcbrk = oldhndlcbrk;
  273. return ( 1 );
  274.     }
  275.             /* EE 2000.4.14 */
  276.             if ( system_yield != NULL )
  277.                 (*system_yield)();
  278. }
  279.         if ( nowait ) goto fail;
  280.     }
  281. fail:
  282.     watcbroke = 0;
  283.     wathndlcbrk = oldhndlcbrk;
  284.     return ( 0 );
  285. }