home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / internet / other / ka9q / nhclb120.zoo / bootp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-18  |  8.6 KB  |  375 lines

  1. /*
  2.  * Center for Information Technology Integration
  3.  *           The University of Michigan
  4.  *                    Ann Arbor
  5.  *
  6.  * Dedicated to the public domain.
  7.  * Send questions to info@citi.umich.edu
  8.  *
  9.  * BOOTP is documented in RFC 951 and RFC 1048
  10.  * Delinted, ANSIfied and reformatted - 5/30/91 P. Karn
  11.  */
  12.  
  13.  
  14. #include <time.h>
  15. #include "global.h"
  16. #include "mbuf.h"
  17. #include "netuser.h"
  18. #include "timer.h"
  19. #include "udp.h"
  20. #include "iface.h"
  21. #include "ip.h"
  22. #include "internet.h"
  23. #include "cmdparse.h"
  24. #include "bootp.h"
  25.  
  26. struct mbuf *htonudp(); 
  27. struct interface *if_lookup();
  28. #ifndef ATARI_ST
  29. static int bootp_rx __ARGS((struct interface *ifp,struct mbuf *bp));
  30. static void ntoh_bootp __ARGS((struct mbuf **bpp,struct bootp *bootpp));
  31. static int mask2width __ARGS((int32 mask));
  32. #else
  33. static int bootp_rx();
  34. static void ntoh_bootp();
  35. static int mask2width();
  36. #endif
  37. #define BOOTP_TIMEOUT    30        /* Time limit for booting       */
  38. #define BOOTP_RETRANS    5        /* The inteval between sendings */
  39.  
  40. int WantBootp = 0;
  41. static int SilentStartup = 0;
  42.  
  43. int
  44. dobootp(argc,argv,p)
  45. int argc;
  46. char *argv[];
  47. char *p;  /* why is this here ? */
  48. {
  49.     struct interface *ifp = NULLIF,*tifp;
  50.     struct socket lsock, fsock;
  51.     struct mbuf *bp;
  52.     struct udp_cb *bootp_cb;
  53.     register char *cp;
  54.     time_t        now,        /* The current time (seconds)   */
  55.               starttime,    /* The start time of sending BOOTP */
  56.               lastsendtime;    /* The last time of sending BOOTP  */
  57.     int i;
  58.  
  59.     ifp = ifaces;            /* default to the first interface */
  60.     if(argc > 1) {
  61.         for(i = 1; i != argc; ++i){
  62.             
  63.             if((tifp = if_lookup(argv[i])) != NULLIF) 
  64.                 ifp = tifp;
  65.             else if(strncmp(argv[i], "silent", strlen(argv[i])) == 0)
  66.                 SilentStartup = 1;
  67.             else if(strncmp(argv[i], "noisy", strlen(argv[i])) == 0)
  68.                 SilentStartup = 0;
  69.             else {
  70.                 printf("bootp [net_name] [silent] [noisy]\n");
  71.                 return 1;
  72.             }
  73.         }
  74.     }
  75.  
  76.     if(ifp == NULLIF)
  77.         return 0;
  78.     lsock.address = 0;
  79.     lsock.port = IPPORT_BOOTPC;
  80.  
  81.     open_udp(&lsock,NULLVFP);
  82.  
  83.     fsock.address = 0xffffffff;
  84.     fsock.port = IPPORT_BOOTPS;
  85.  
  86.       /* Get boot starting time */
  87.       time(&starttime);
  88.       lastsendtime = 0;
  89.  
  90.       /* Send the bootp request packet until a response is received or time
  91.        out */
  92.       for(;;){
  93.  
  94.         /* Allow bootp packets should be passed through iproute. */
  95.         WantBootp = 1;
  96.  
  97.         /* Get the current time */
  98.         time(&now);
  99.  
  100.         /* Stop, if time out */
  101.         if(now - starttime >= BOOTP_TIMEOUT){
  102.             printf("bootp: timed out, values not set\n");
  103.             break;
  104.         }
  105.  
  106.         /* Don't flood the network, send in intervals */
  107.         if(now - lastsendtime > BOOTP_RETRANS){
  108.             if(!SilentStartup) printf("Requesting...\n");
  109.  
  110.             /* Allocate BOOTP packet and fill it in */
  111.             if((bp = alloc_mbuf(sizeof(struct bootp))) == NULLBUF)
  112.                 break;
  113.             cp = bp->data;        /* names per the RFC: */
  114.             *cp++ = BOOTREQUEST;        /* op */
  115.             *cp++ = 1; /* ifp->iftype->type;    /* htype */
  116.             *cp++ = 6; /* ifp->iftype->hwalen;    /* hlen */
  117.             *cp++ = 0;            /* hops */
  118.             cp = put32(cp,(int32) now);    /* xid */
  119.             cp = put16(cp, now - starttime);/* secs */
  120.             cp = put16(cp, 0);        /* unused */
  121.             cp = put32(cp, ip_addr);    /* ciaddr */
  122.             cp = put32(cp, 0L);        /* yiaddr */
  123.             cp = put32(cp, 0L);        /* siaddr */
  124.             cp = put32(cp, 0L);        /* giaddr */
  125.             if (ifp->hwaddr) {
  126.                 memcpy(cp, ifp->hwaddr, 6);
  127.                 cp += 16;            /* chaddr */
  128.             } else {
  129.                 memset(cp, 0, 16);        /* chaddr */
  130.                 cp += 16;
  131.             }
  132.             memset(cp, 0, 64);        /* sname */
  133.             cp += 64;
  134.             memset(cp, 0, 128);        /* file */
  135.             cp += 128;
  136.             memset(cp, 0, 64);        /* vend */
  137.             cp += 64;
  138.             bp->cnt = cp - bp->data;
  139.             /* assert(bp->cnt == BOOTP_LEN) */
  140.  
  141.             /* Send out one BOOTP Request packet as a broadcast */
  142.             send_udp(&lsock, &fsock,0,0,bp,bp->cnt,0,0);
  143.  
  144.             lastsendtime = now;
  145.         }
  146.  
  147.         /* Give other tasks a chance to run. */
  148. /*        pwait(NULL);*/
  149.         keep_things_going();
  150.  
  151.         /* Test for and process any replies */
  152.         if(recv_udp(&lsock, &fsock, &bp) > -1){
  153.             if(bootp_rx(ifp,bp))
  154.                 break;
  155.         } else if(net_error != WOULDBLK){
  156.             printf("bootp: Net_error %d, no values set\n",
  157.                  net_error);
  158.             break;
  159.         }
  160.       }
  161.  
  162.     WantBootp = 0;
  163.     del_udp(&lsock);
  164.     return 0;
  165. }
  166.  
  167. /* Process BOOTP input received from 'interface'. */
  168. static int
  169. bootp_rx(ifp,bp)
  170. struct interface *ifp;
  171. struct mbuf *bp;
  172. {
  173.     int         ch;
  174.     int            count;
  175.     int32         gateway = 0;
  176.     int32         nameserver = 0;
  177.     int32         broadcast, netmask;
  178.     struct route     *rp;
  179.     struct bootp    reply;
  180.     char        *cp;
  181.  
  182.     if(len_mbuf(bp) != sizeof(struct bootp)){
  183.         free_p(bp);
  184.         return 0;
  185.     }
  186.     ntoh_bootp(&bp, &reply);
  187.     free_p(bp);
  188.  
  189.     if(reply.op != BOOTREPLY) 
  190.         return 0;
  191.  
  192.     if(!SilentStartup)
  193.         printf("Network %s configured:\n", ifp->name);
  194.  
  195.     if(ip_addr == 0){
  196.         ip_addr = (int) reply.yiaddr;    /* yiaddr */
  197.         if(!SilentStartup)
  198.             printf("     IP address: %s\n",  
  199.         inet_ntoa(ip_addr));
  200.     }
  201.  
  202. #ifdef undef
  203.     /* now process the vendor-specific block, check for cookie first. */
  204.     cp = reply.vend;
  205.     if(get32(cp) != 0x63825363L){
  206.         printf("Invalid magic cookie.\n");
  207.         return(0);
  208.     }
  209.  
  210.     cp += 4;
  211.     while(((ch = *cp) != BOOTP_END) && (++cp < (reply.vend + 64))) 
  212.         switch(ch){
  213.         case BOOTP_PAD:        /* They're just padding */
  214.             continue;
  215.         case BOOTP_SUBNET:    /* fixed length, 4 octets */
  216.             cp++;        /* moved past length */
  217.  
  218.             /* Set the netmask */
  219.                 /* Remove old entry if it exists */
  220.             netmask = get32(cp);
  221.             cp += 4;
  222.  
  223.                 rp = rt_blookup(ifp->addr & ifp->netmask,mask2width(ifp->netmask));
  224.                 if(rp != NULLROUTE)
  225.                         rt_drop(rp->target,rp->bits);
  226.                 ifp->netmask = netmask;
  227.                 rt_add(ifp->addr,mask2width(ifp->netmask),0L,ifp,0L,0L,0);
  228.  
  229.             if(!SilentStartup)
  230.                 printf("     Subnet mask: %s\n", inet_ntoa(netmask));
  231.             
  232.             /* Set the broadcast */
  233.             broadcast = ifp->addr | ~(ifp->netmask);
  234.                 rp = rt_blookup(ifp->broadcast,32);
  235.                 if(rp != NULLROUTE && rp->iface == ifp)
  236.                         rt_drop(ifp->broadcast,32);
  237.                 ifp->broadcast = broadcast;
  238.                 rt_add(ifp->broadcast,32,0L,ifp,1L,0L,1);
  239.             
  240.             if(!SilentStartup)
  241.                 printf("     Broadcast: %s\n", inet_ntoa(broadcast));
  242.  
  243.             break;
  244.         case BOOTP_HOSTNAME:
  245.             count = (int) *cp;
  246.             cp++;
  247.  
  248.             if(Hostname != NULLCHAR)
  249.                 free(Hostname);
  250.             Hostname = mallocw(count);
  251.             strncpy(Hostname, cp, count);
  252.             cp += count;
  253.  
  254.             if(!SilentStartup)
  255.                 printf("     Hostname: %s\n", Hostname);
  256.             break;
  257.         case BOOTP_DNS:
  258.             count = (int) *cp;
  259.             cp++;
  260.  
  261.             while(count){
  262.                 nameserver = get32(cp);
  263.                 add_nameserver(nameserver);
  264.                 if(!SilentStartup)
  265.                     printf("     Nameserver: %s\n", inet_ntoa(nameserver));
  266.                 cp += 4;
  267.                 count -= 4;
  268.             }
  269.             break;
  270.         case BOOTP_GATEWAY:
  271.             count = (int) *cp;
  272.             cp++;
  273.  
  274.             gateway = get32(cp);
  275.  
  276.             /* Add the gateway as the default */
  277.             rt_add(0,0,gateway,ifp,1,0,0);
  278.  
  279.             if(!SilentStartup)
  280.                 printf("     Default gateway: %s\n", inet_ntoa(gateway));
  281.             cp += count;
  282.             break;
  283.         default:        /* variable field we don't know about */
  284.             count = (int) *cp;
  285.             cp++;
  286.  
  287.             cp += count;
  288.             break;
  289.     }
  290.  
  291.     rt_add(ifp->addr,mask2width(ifp->netmask),0L,ifp,1,0,0);
  292. #endif
  293.     return(1);
  294. }
  295.  
  296.  
  297. static void
  298. ntoh_bootp(bpp, bootpp)
  299. struct mbuf **bpp;
  300. struct bootp *bootpp;
  301. {
  302.     bootpp->op = pullchar(bpp);                     /* op */
  303.     bootpp->htype = pullchar(bpp);            /* htype */
  304.     bootpp->hlen = pullchar(bpp);            /* hlen */
  305.     bootpp->hops = pullchar(bpp);            /* hops */
  306.     bootpp->xid = pull32(bpp);            /* xid */
  307.     bootpp->secs = pull16(bpp);            /* secs */
  308.     bootpp->unused = pull16(bpp);            /* unused */
  309.     bootpp->ciaddr = pull32(bpp);        /* ciaddr */
  310.     bootpp->yiaddr = pull32(bpp);        /* ciaddr */
  311.     bootpp->siaddr = pull32(bpp);        /* siaddr */
  312.     bootpp->giaddr = pull32(bpp);        /* giaddr */
  313.     pullup(bpp, bootpp->chaddr, 16);        /* chaddr */
  314.     pullup(bpp, bootpp->sname, 64);        /* sname */
  315.     pullup(bpp, bootpp->file, 128);        /* file name */
  316.     pullup(bpp, bootpp->vend, 64);            /* vendor */
  317. }
  318.  
  319.  
  320.  
  321.  
  322. int
  323. bootp_validPacket(ip, bpp)
  324. struct ip *ip;
  325. struct mbuf **bpp;
  326. {
  327.     struct udp udp;
  328.     struct pseudo_header ph;
  329.     int status;
  330.  
  331.  
  332.     /* Must be a udp packet */
  333.     if(ip->protocol !=  UDP_PTCL) 
  334.         return 0;
  335.  
  336.     /* Invalid if packet is not the right size */
  337.     if(len_mbuf(*bpp) != (sizeof(struct udp) + sizeof(struct bootp)))
  338.         return 0;
  339.  
  340.     /* Invalid if not a udp bootp packet */
  341.     ntohudp(&udp, bpp);
  342.  
  343.     status = (udp.dest == IPPORT_BOOTPC) ? 1 : 0;
  344.     
  345.     /* Restore packet, data hasn't changed */
  346.         /* Create pseudo-header and verify checksum */
  347.         ph.source = ip->source;
  348.         ph.dest = ip->dest;
  349.         ph.protocol = ip->protocol;
  350.         ph.length = ip->length - IPLEN - ip->optlen;
  351.  
  352.     *bpp = htonudp(&udp, *bpp, &ph);
  353.  
  354.     return status;
  355. }
  356.  
  357. /* Given a network mask, return the number of contiguous 1-bits starting
  358.  * from the most significant bit.
  359.  */
  360. static int
  361. mask2width(mask)
  362. int32 mask;
  363. {
  364.         int width,i;
  365.  
  366.         width = 0;
  367.         for(i = 31;i >= 0;i--){
  368.                 if(!(mask & (1L << i)))
  369.                         break;
  370.                 width++;
  371.         }
  372.         return width;
  373. }
  374.  
  375.