home *** CD-ROM | disk | FTP | other *** search
/ GRIPS 2: Government Rast…rocessing Software & Data / GRIPS_2.cdr / dos / ncsa_tel / contribu / byu_tel2.hqx / tcpip / dlayer.c < prev    next >
Text File  |  1988-07-12  |  11KB  |  400 lines

  1. /*   
  2. *     DLAYER
  3. *     Hardware level routines, data link layer
  4. *
  5. ****************************************************************************
  6. *                                                                          *
  7. *      part of:                                                            *
  8. *      TCP/IP kernel for NCSA Telnet                                       *
  9. *      by Tim Krauskopf                                                    *
  10. *                                                                          *
  11. *      National Center for Supercomputing Applications                     *
  12. *      152 Computing Applications Building                                 *
  13. *      605 E. Springfield Ave.                                             *
  14. *      Champaign, IL  61820                                                *
  15. *                                                                          *
  16. *    Copyright (c) 1987, Board of Trustees of the University of Illinois   *
  17. *                                                                          *
  18. ****************************************************************************
  19. */
  20. #include "stdio.h"
  21. #include "protocol.h"
  22. #include "data.h"
  23.  
  24. /************************************************************************/
  25. /*
  26. *   Address Resolution Protocol handling.  This can be looked at as
  27. *   Ethernet-dependent, but the data structure can handle any ARP
  28. *   hardware, with minor changes here.
  29. *
  30. */
  31. replyarp(thardware,tipnum)
  32.     uint8 *thardware,*tipnum;
  33.     {
  34.     uint8 *pc;
  35.  
  36.     movebytes(&arp.tha,thardware,DADDLEN);   /* who this goes to */
  37.  
  38.     movebytes(&arp.tpa,tipnum,4);        /* requester's IP address */
  39.     arp.op = intswap(ARPREP);            /* byte swapped reply opcode */
  40.  
  41.     movebytes(arp.d.dest,thardware,DADDLEN);    /* hardware place to send to */
  42.  
  43.     dlayersend(&arp,sizeof(arp));
  44.  
  45. /*
  46. *  check for conflicting IP number with your own
  47. */
  48.     if (comparen(tipnum,nnipnum,4))    {     /* we are in trouble */
  49.         pc = neterrstring(-1);
  50.         sprintf(pc,"Conflict with Ethernet hardware address: %2x:%2x:%2x:%2x:%2x:%2x",
  51.         thardware[0],thardware[1],thardware[2],thardware[3],thardware[4],thardware[5]);
  52.         netposterr(-1);
  53.         netposterr(102);
  54.         return(-3);
  55.     }
  56.  
  57. }
  58.  
  59. /************************************************************************/
  60. /*  reqarp
  61. *    put out an ARP request packet, doesn't wait for response
  62. */
  63. reqarp(tipnum)
  64.     uint8 *tipnum;
  65.     {
  66.  
  67. #ifdef MAC
  68.     if (KIP) {
  69.         if (0 < KIParp(tipnum,&arp.tha))
  70.             cacheupdate(tipnum, &arp.tha);
  71.         return(0);
  72.     }
  73. #endif MAC
  74.  
  75.     movebytes(&arp.tha,broadaddr,DADDLEN); 
  76.     movebytes(&arp.tpa,tipnum,4);              /* put in IP address we want */
  77.     arp.op = intswap(ARPREQ);                /* request packet */
  78.  
  79.     movebytes(arp.d.dest,broadaddr,DADDLEN);        /* send to everyone */
  80.  
  81.     if (dlayersend(&arp,sizeof(arp)))
  82.         return(1);                          /* error return */
  83.  
  84.     return(0);
  85. }
  86.  
  87. /************************************************************************/
  88. /*  interpret ARP packets
  89. *   Look at incoming ARP packet and make required assessment of usefulness,
  90. *   check to see if we requested this packet, clear all appropriate flags.
  91. */
  92. arpinterpret(p)
  93.     ARPKT *p;
  94.     {
  95.  
  96. /*
  97. *  check packet's desired IP address translation to see if it wants
  98. *  me to answer.
  99. */
  100.     if (p->op == intswap(ARPREQ) && (comparen(&p->tpa,nnipnum,4))) { 
  101.  
  102.         cacheupdate(&p->spa,&p->sha);   /* keep her address for me */
  103.  
  104.         replyarp(&p->sha,&p->spa);        /* proper reply */
  105.         return(0);
  106.     }
  107. /*
  108. *  Check for a RARP reply.  If present, call netsetip()
  109. */
  110.     else if (p->op == intswap(RARPR) && (comparen(&p->tha,nnmyaddr,DADDLEN))) {
  111.         movebytes(nnipnum,&p->tpa,4);
  112.         return(0);
  113.     }
  114.  
  115. /* 
  116. *  Check for a reply that I probably asked for.
  117. */
  118.     if (comparen(&p->tpa,nnipnum,4)) {
  119.         if (p->op == intswap(ARPREP) &&
  120.             p->hrd == intswap(HTYPE) &&       /* consistency checking */
  121.             p->hln == DADDLEN &&
  122.             p->pln == 4 ) {
  123.             cacheupdate(&p->spa,&p->sha);
  124.             return(0);
  125.         }
  126.     }
  127.  
  128.     return(1);
  129.  
  130. }
  131.  
  132. /*************************************************************************/
  133. /* rarp
  134. *  Send a rarp request to look up my IP number
  135. */
  136. rarp()
  137.     {
  138. /*
  139. *  our other fields should already be loaded
  140. */
  141.     movebytes(&arp.tha,nnmyaddr,DADDLEN);   /* address to look up (me) */
  142.     movebytes(&arp.sha,nnmyaddr,DADDLEN);   /* address to look up (me) */
  143.     arp.op = intswap(RARPQ);                /* request packet */
  144.  
  145.     movebytes(arp.d.dest,broadaddr,DADDLEN);        /* send to everyone */
  146.     arp.d.type = ERARP;
  147.  
  148.     if (dlayersend(&arp,sizeof(arp)))
  149.         return(1);                          /* error return */
  150.  
  151.     arp.d.type = EARP;                        /* set back for ARP to use */
  152.     return(0);
  153.  
  154. }
  155.  
  156. /*************************************************************************/
  157. /* cacheupdate
  158. *  We just received an ARP, or reply to ARP and need to add the information
  159. *  to the cache.
  160. *
  161. *  Reset arptime so that another machine may be ARPed.  This timer keeps
  162. *  ARPs from going out more than one a second unless we receive a reply.
  163. */
  164. static int32 arptime=0L;
  165.  
  166. cacheupdate(ipn,hrdn)
  167.     uint8 *ipn,*hrdn;
  168.     {
  169.     int i,found;
  170.     int32 timer;
  171.  
  172.     found = -1;
  173. /*
  174. * linear search to see if we already have this entry
  175. */
  176.     for (i=0; found < 0 && i < CACHELEN; i++) 
  177.         if (comparen(ipn,&arpc[i].ip,4))
  178.             found = i;
  179.  
  180. /*
  181. *  if that IP number is not already here, take the oldest entry.
  182. *  If it is already here, update the info and reset the timer.
  183. *  These were pre-initialized to 0, so if any are blank, they will be
  184. *  taken first because they are faked to be oldest.
  185. */
  186.     if (found < 0) {
  187.         timer = arpc[0].tm;
  188.         found = 0;
  189.  
  190.         for (i=1; i < CACHELEN; i++) 
  191.             if (arpc[i].tm < timer && !arpc[i].gate) {/* exclude gateways */
  192.                 found = i;
  193.                 timer = arpc[i].tm;
  194.             }
  195.     }
  196. /*
  197. *   do the update to the cache
  198. */
  199.  
  200.     movebytes(&arpc[found].hrd,hrdn,DADDLEN);
  201.     movebytes(&arpc[found].ip,ipn,4);
  202.     arpc[found].tm = time(NULL);
  203.  
  204.     arptime = 0L;                    /* reset, allow more arps */
  205.     return(found);
  206.  
  207. }
  208.  
  209. /*************************************************************************/
  210. /*  cachelook
  211. *   look up information in the cache
  212. *   returns the cache entry number for the IP number given.
  213. *   Returns -1 on no valid entry, also if the entry present is too old.
  214. *
  215. *   doarp is a flag for non-gateway requests which determines whether an
  216. *   arp will be sent or not.
  217. */
  218.  
  219. cachelook(ipn,gate,doarp)
  220.     uint8 *ipn;
  221.     int gate,doarp;
  222.     {
  223.     int i,haveg;
  224. /*
  225. *  First option, we are not looking for a gateway, but a host on our
  226. *  local network.
  227. */
  228.     if (!gate) {
  229.         for (i=0; i<CACHELEN; i++)
  230.             if (comparen(ipn,&arpc[i].ip,4) && 
  231.                 arpc[i].tm + CACHETO > time(NULL)) 
  232.                 return(i);
  233. /*
  234. *  no valid entry, send an ARP
  235. */
  236.         if (time(NULL) >= arptime && doarp) {    /* check time limit */
  237.             reqarp(ipn);                /* put out a broadcast request */
  238.             arptime = time(NULL)+ARPTO;
  239.         }
  240.         return(-1);
  241.     }
  242.     else {
  243. /*
  244. *  Second option, we need a gateway.
  245. *  if there is a gateway with a current ARP, use it.
  246. *  if not, arp all of the gateways and return an error.  Next call will
  247. *  probably catch the result of the ARP.
  248. */
  249.         haveg = 0;
  250.         for (i=CACHELEN-1; i >= 0; i--)
  251.             if (arpc[i].gate && arpc[i].tm + CACHETO > time(NULL))
  252.                 return(i);
  253.  
  254.         if (time(NULL) >= arptime) {    
  255.             for (i=CACHELEN-1; i >= 0; i--)
  256.                 if (arpc[i].gate) {
  257.                     haveg = 1;
  258.                     reqarp(&arpc[i].ip);    /* put out a broadcast request */
  259.                 }
  260.  
  261.             if (!haveg)             /* blind luck, try ARPing even for */
  262.                 reqarp(ipn);        /* a node not on our net. (proxy ARP)*/
  263.  
  264.             arptime = time(NULL)+ARPTO;
  265.         }
  266.  
  267.         return(-1);
  268.     }
  269.  
  270. }
  271.  
  272.  
  273.  
  274. /***************************************************************************/
  275. /*  netdlayer
  276. *       get data layer address for insertion into outgoing packets.
  277. *   searches based on ip number.  If it finds the address, ok, else . . .
  278. *
  279. *   Checks to see if the address is on the same network.  If it is,
  280. *   then ARPs the machine to get address.  Forces pause between sending
  281. *   arps to guarantee not saturating network.
  282. *
  283. *   If not on the same network, it needs the ether address of a 
  284. *   gateway.  Searches the list of machines for a gateway flag.
  285. *   Returns the first gateway found with an Ethernet address. 
  286. *
  287. *   Returns NULL if not here, or pointer to ether address
  288. *   If we don't have it, this also sends an ARP request so that the
  289. *   next time we are called, the ARP reply may be here by then.
  290. *
  291. */
  292. uint8
  293. *netdlayer(tipnum)
  294.     uint8 *tipnum;
  295.     {
  296.     int32 t;
  297.     uint8 *pc;
  298.  
  299.     t = time(NULL) + nndto*TICKSPERSEC;            /* some seconds time out */
  300.     pc = NULL;
  301.     do {
  302.         if (t <= time(NULL))                     /* timed out */
  303.             return(NULL);
  304.         pc = getdlayer(tipnum);
  305.         netsleep(0);                            /* can't have deadlock */
  306.     } while (pc == NULL);
  307.  
  308.     return(pc);
  309. }
  310.  
  311. /***************************************************************************/
  312. /*  netgetrarp
  313. *   Look for a RARP response to arrive
  314. *   wait for nndto seconds before returning failure.
  315. *   If response arrives, return success.
  316. */
  317. netgetrarp()
  318.     {
  319.     int32 t,tr;
  320.  
  321.     t = time(NULL) + nndto*TICKSPERSEC*3;        /* some seconds time out */
  322.     tr = 0L;                                    /* one second retry */
  323.  
  324.     do {
  325.         if (tr <= time(NULL)) {                    /* need retry? */
  326.             rarp();
  327.             tr = time(NULL) + TICKSPERSEC;
  328.         }
  329.  
  330.         if (t <= time(NULL)) {                    /* timed out */
  331.             netposterr(103);
  332.             return(-1);
  333.         }
  334.  
  335.         netsleep(0);                            /* can't have deadlock */
  336.     } while (comparen(nnipnum,"RARP",4));        /* until RARP is served */
  337.  
  338.     return(0);
  339. }
  340.  
  341. /***************************************************************************/
  342. /*  getdlayer
  343. *   check for the hardware address one time
  344. */
  345. uint8
  346. *getdlayer(tipnum)
  347.     uint8 *tipnum;
  348.     {
  349.     int needgate,i;
  350.  
  351.     needgate = 0;
  352.  
  353. /*
  354. *  Check to see if we need to go through a gateway.
  355. *  If the machine is on our network, then assume that we can send an ARP
  356. *  to that machine, otherwise, send the ARP to the gateway.
  357. *
  358. *  Uses internet standard subnet mask method, RFC950
  359. *  if subnets are not in use, netmask has been pre-set to the appropriate 
  360. *  network addressing mask.
  361. */ 
  362.     for (i=3; i >= 0; i--)
  363.         if ((nnmask[i] & tipnum[i]) != (nnmask[i] & nnipnum[i]))
  364.             needgate = 1;
  365.  
  366.     if (needgate && (0 <= (i = cachelook(tipnum,1,1)))) 
  367.         return(&arpc[i].hrd);
  368.  
  369.     if (!needgate && (0 <= (i = cachelook(tipnum,0,1))))
  370.         return(&arpc[i].hrd);
  371.  
  372.     return(NULL);
  373. }
  374.  
  375. /***************************************************************************/
  376. /*  netsetgate
  377. *   Establish an IP number to use as a gateway.
  378. *   They are added in the order that they arrive and there is a limit on
  379. *   the number of gateways equal to CACHELEN/2.
  380. *   ARPs them as they are added so that the Cache will get pre-filled
  381. *   with gateways.
  382. *
  383. *   returns 0 if ok, -1 on error (full)
  384. */
  385. netsetgate(ipn)
  386.     uint8 *ipn;
  387.     {
  388.     int i;
  389.  
  390.     for (i=CACHELEN-1 ; i >= CACHELEN/2 ; i--)
  391.         if (!arpc[i].gate) {
  392.             arpc[i].gate = 1;
  393.             movebytes(&arpc[i].ip,ipn,4);
  394.             reqarp(ipn);
  395.             return(0);
  396.         }
  397.  
  398.     return(-1);
  399. }
  400.