home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / NETWORK / TEL23SRC.ZIP / ENGINE / BOOTP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-25  |  7.4 KB  |  288 lines

  1. /*   
  2.  *     BOOTP
  3.  *     Bootp Routines
  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.  ****************************************************************************
  17.  */
  18.  
  19. #define REALTIME
  20. /*#define DEBUG       /* for debug prints */
  21. #include "debug.h"
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <time.h>
  26. #include <string.h>
  27. #ifdef MSC
  28. #ifdef __TURBOC__
  29. #include <alloc.h>
  30. #else
  31. #include <malloc.h>
  32. #endif
  33. #endif
  34.  
  35. #ifdef MEMORY_DEBUG
  36. #include "memdebug.h"
  37. #endif
  38. #include "protocol.h"
  39. #include "data.h"
  40. #include "bootp.h"
  41. #include "windat.h"
  42. #include "hostform.h"
  43. #include "data.h"
  44. #include "externs.h"
  45.  
  46. /*
  47.  *    Bootp routines : from the Clarkson 2.2 version of NCSA Telnet.
  48.  *    Thanks to Brad Clements for implementing this!
  49.  *
  50.  * bootp routines - These routines are based on the stanford/clarkson
  51.  * bootp code. Originally developed at Stanford University.
  52.  *
  53.  * Bootp is a UDP based protocol that determines the clients IP address and
  54.  * gateway information etc.
  55.  */
  56.  
  57. static struct bootp    bootpacket;
  58. static u_long    bootp_xid;
  59. extern int foundbreak;
  60.  
  61. /* Local functions */
  62. static int sendbootp(void );
  63. static void bootp_init(void );
  64. static int parse_bootpacket(struct bootp *bp);
  65.  
  66. /* sends a bootp broadcast packet */
  67. /* this routine does not do the initial setup of the bootp packet */
  68.  
  69. static int sendbootp()
  70. {
  71.     return(netusend(broadip,IPPORT_BOOTPS,IPPORT_BOOTPC, (unsigned char *)&bootpacket, (int)sizeof(struct bootp)));
  72. }
  73.  
  74. /* initialize the bootp packet */
  75. static void bootp_init()
  76. {
  77.     bootp_xid=time(NULL);   /* get a unique transaction ID */
  78.     memset((char *) &bootpacket,0,sizeof(bootpacket));
  79.     bootpacket.bp_op=BOOTREQUEST;
  80.     bootpacket.bp_htype=1;     /* hardware type 1 is ethernet. This should be made more robust. */
  81.     bootpacket.bp_hlen=sizeof(nnmyaddr);
  82.     bootpacket.bp_xid=bootp_xid;
  83.     bootpacket.bp_secs=1;
  84.     memcpy(bootpacket.bp_chaddr, nnmyaddr, sizeof(nnmyaddr));
  85. }
  86.  
  87. /* parse an incoming bootp packet */
  88. static int parse_bootpacket(bp)
  89. struct bootp *bp;
  90. {
  91.     int     x,items,len;
  92.     unsigned char *c;
  93.     char message[80],*cp;
  94.     int gateway=0,nameserver=0;
  95.     struct machinfo *sp;
  96.     extern struct config Scon;
  97.     extern struct machinfo *Sns;
  98.  
  99.     netsetip(&bp->bp_yiaddr.addr[0]);             /* set my ip address */
  100.     movebytes(Scon.myipnum,&bp->bp_yiaddr,4);
  101.     if(comparen(bp->bp_vend,VM_RFC1048,4)) {
  102.         c=bp->bp_vend+4;
  103.         while((*c!=255)&&((c-bp->bp_vend)<64)) {
  104.             switch(*c) {
  105.                 case 0:        /* nop pad */
  106.                     c++;
  107.                     break;
  108.  
  109.                 case 1:        /* subnet mask */
  110.                     len=*(c+1);
  111.                     c+=2;
  112.                     memcpy(Scon.netmask,c, 4);
  113.                     netsetmask(Scon.netmask);
  114.                     c+=len;
  115.                     Scon.havemask=1;
  116.                     break;
  117.  
  118.                 case 2:        /* time offset */
  119.                     c+=*(c+1)+2;
  120.                     break;
  121.  
  122.                 case 3:        /* gateways     */
  123.                     len=*(c+1);
  124.                     items=len/4;
  125.                     c+=2;
  126.                     for(x=0; x<items; x++) {
  127.                         sprintf(message,"%d.%d.%d.%d",*c, *(c+1), *(c+2), *(c+3));
  128.                         if(!(sp=Smadd(message))) {
  129.                             printf("Out of Memory Adding Gateway-Smadd()\n\r");
  130.                             return(-1);
  131.                           }
  132.                         gateway++;
  133.                         sprintf(message,"BootP: Adding Gateway number %d IP %s\n\r",gateway,sp->hname);
  134.                         sp->gateway=(unsigned char)gateway;
  135.                         memcpy(sp->hostip,c,4);
  136.                         sp->mstat=HFILE;
  137.                         c+=4;
  138.                       }
  139.                     break;
  140.  
  141.                 case 4:        /* time servers */
  142.                 case 5:        /* IEN=116 name server */
  143.                     c+=*(c+1)+2;
  144.                     break;
  145.  
  146.                 case 6:        /* domain name server */
  147.                     len=*(c+1);
  148.                     items=len/4;
  149.                     c+=2;
  150.                     for(x=0; x<items; x++) {
  151.                         sprintf(message,"%d.%d.%d.%d",*c, *(c+1), *(c+2), *(c+3));
  152.                         if(!(sp=Smadd(message))) {
  153.                             printf("Out of Memory Adding Nameserver-Smadd()\n\r");
  154.                             return(-1);
  155.                           }
  156.                         nameserver++;
  157.                         sp->nameserv=(unsigned char)nameserver;
  158.                         memcpy(sp->hostip,c,4);
  159.                         sp->mstat=HFILE;
  160.                         if(!Sns)
  161.                             Sns=sp;
  162.                         c+=4;
  163.                       }
  164.                     Scon.nstype=1;
  165.                     break;
  166.                 
  167.                 case 7:        /* log server */
  168.                 case 8:        /* cookie server */
  169.                 case 9:        /* lpr server */
  170.                 case 10:        /* impress server */
  171.                 case 11:        /* rlp server */
  172.                     c+=*(c+1)+2;
  173.                     break;
  174.     
  175.                 case 12:        /* client host name    */
  176.                     len=*(c+1);
  177.                     strncpy(message,c+2, len);
  178.                     message[len]=0;
  179.                     if(!(sp=Smadd(message))) {
  180.                         printf("Out of Memory Adding client name-Smadd()\n\r");
  181.                         return(-1);
  182.                       }
  183.                     if(!strlen(Scon.me)) 
  184.                         strncpy(Scon.me,sp->hname,31);
  185.                     Scon.me[31]=0;
  186.                     if(cp=strchr(sp->hname,'.')) {     /* assume fully qualified name if a . is in hostname */
  187. #ifdef LATER
  188.                         if(!Scon.domainpath) { /* if no domain set yet */
  189.                             message[0]=0;
  190.                             while(cp) {
  191.                                 strcat(message,",");
  192.                                 strcat(message,cp+1);
  193.                                 cp=strchr(cp+1,'.');
  194.                               }
  195.                             Scon.domainpath=malloc(strlen(message)+1);
  196.                             strcpy(Scon.domainpath, message);
  197.                             removejunk(Scon.domainpath);
  198.                           }
  199. #endif
  200.                       }
  201.                     c+=len+2;
  202.                     break;
  203.  
  204.                 case 255:
  205.                     break;
  206.  
  207.                 default:
  208.                     c+=*(c+1)+2;
  209.                     break;                        
  210.               }                /* end switch */
  211.           }                    /* end while    */
  212.       }                        /* end if comparen */
  213.     if(!gateway) {            /* if none were in the rfc1048 vend packet, add the default gateway as an entry */
  214.         c=bp->bp_giaddr.addr;
  215.         sprintf(message,"%d.%d.%d.%d",*c, *(c+1), *(c+2), *(c+3));
  216.         if(!(sp=Smadd(message))) {
  217.             printf("Out of Memory Adding Gateway-Smadd()\n\r");
  218.             return(-1);
  219.           }
  220.         gateway++;
  221.         sp->gateway=(unsigned char)gateway;
  222.         memcpy(sp->hostip,c,4);
  223.         sp->mstat=HFILE;
  224.       }
  225.     return(0);
  226. }
  227.  
  228. /*
  229. *   main processing of bootp lookup request calls 
  230. *        sendbootp to send a bootp request,
  231. *  sets up the udp listen port etc, handles retries
  232. */
  233. int bootp()    
  234. {
  235.     int x,y,delay;
  236.     time_t start_time;
  237.     union {
  238.         char junk_buff[1506];
  239.         struct bootp bootpacket;
  240.     } udp_data;
  241.     unsigned char *ea;
  242.     struct bootp *bp;
  243.     static unsigned char myip[]={0,0,0,0};
  244.  
  245. BUG("bootp()");
  246.     time(&start_time);
  247.     netsetip(myip);
  248.     bootp_init();
  249. BUG("after bootp_init");
  250.     bp=&udp_data.bootpacket;
  251.     ea=(unsigned char *) nnmyaddr;
  252.     while(neturead(udp_data.junk_buff)!=-1);    /* should only go around once */
  253.     for(x=0; x<BOOTP_RETRIES; x++) {
  254.         netulisten(IPPORT_BOOTPC);
  255. BUG("sending bootp");
  256.         if(y=sendbootp()) {                /* do some error processing */
  257.             printf("\n\rError %d from sendbootp\n\r",y);
  258.             return(-1);
  259.         }
  260. BUG("bootp sent");
  261.         start_time=time(NULL);
  262.         delay=((rand() % 10)+1);
  263.         while((time(NULL)-start_time)<(long) delay) {
  264.             if(!demux(1))
  265.                 continue;         /* process all packets */
  266.             if(neturead(udp_data.junk_buff) ==-1) 
  267.                 continue;
  268.             delay=0;
  269.             break;
  270.         }
  271. BUG("done waiting");
  272.         if(delay)
  273.             continue;        /* time ran out and got nothing */
  274.         if(((bp->bp_xid)==bootp_xid) && ((bp->bp_op)==BOOTREPLY) &&
  275.           comparen(bp->bp_chaddr,nnmyaddr,sizeof(nnmyaddr)))
  276.             break;             /* got a valid reply */
  277.     }
  278.     if(x==BOOTP_RETRIES) {        /* do some error processing */
  279.         printf("\nBOOTP Timeout. No Response from BOOTP server\n\r");
  280.         return(-1);
  281.     }
  282. BUG("About to parser bootp packet");
  283.     if(parse_bootpacket(bp))
  284.         return(-1);
  285.     return(0);
  286. }
  287.  
  288.