home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / WATTCP / WNWATTCP.ZIP / SRC / PCBOOTP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-07  |  5.8 KB  |  180 lines

  1. /*
  2.  *
  3.  *   BOOTP - Boot Protocol (RFC 854)
  4.  *
  5.  *   These extensions get called if _bootphost is set to an IP address or
  6.  *   to 0xffffffff.
  7.  *
  8.  *   Version
  9.  *
  10.  *   0.2 : May 22, 1991 : E.J. Sutcliffe - added RFC_1048 vendor fields
  11.  *   0.1 : May  9, 1991 : E. Engelke - made part of the library
  12.  *   0.0 : May  3, 1991 : E. Engelke - original program as an application
  13.  *
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include "copyright.h"
  18. #include "wattcp.h"
  19. #include "bootp.h"
  20. #include "errors.h"
  21.  
  22. /* global variables */
  23. longword _bootphost = 0xffffffffL;
  24. word _bootptimeout = 30;
  25. word _bootpon = 0;
  26.  
  27. extern longword set_timeout();
  28.  
  29. #define VM_RFC1048 0x63825363L    /* I think this is correct */
  30.  
  31. /*
  32.  * _dobootpc - Checks global variables _bootptimeout, _bootphost
  33.  *             if no host specified, the broadcast address
  34.  *             returns 0 on success and sets ip address
  35.  */
  36. int _dobootp()
  37. {
  38.     udp_Socket bsock;
  39.     longword sendtimeout, bootptimeout;
  40.     word magictimeout;
  41.     word len, templen;
  42.     struct bootp sendbootp;     /* outgoing data */
  43.     struct bootp _bootp;        /* incoming data */
  44.     int status;
  45.     longword xid;
  46.     unsigned char *p,*t;
  47.  
  48.     if ( _pktdevclass == PD_SLIP ) return(ER_CONF);
  49.  
  50.     /* We must get Waterloo TCP to use IP address 0 for sending */
  51.     xid = my_ip_addr;   /* a unique value coming from the ethernet card */
  52.     my_ip_addr = 0;
  53.  
  54.     if (!udp_open( &bsock, IPPORT_BOOTPC, _bootphost, IPPORT_BOOTPS, NULL )) {
  55.         return(ER_CONF);
  56.     }
  57.  
  58.     bootptimeout = set_timeout( _bootptimeout );
  59.     magictimeout = (xid & 7) + 7;  /* between 7 and 14 seconds */
  60.  
  61.     memset( &sendbootp, 0, sizeof( struct bootp ));
  62.     sendbootp.bp_op = BOOTREQUEST;
  63.     sendbootp.bp_htype = _pktdevclass;
  64.     /* Copy into position the Magic Number used by Bootp */
  65.     /* avoid static storage and pushf/call assembler instructions */
  66.     *(longword *)(&sendbootp.bp_vend) = intel(VM_RFC1048);
  67.  
  68.     if (_pktdevclass == PD_ETHER) sendbootp.bp_hlen = 6;
  69.  
  70.     sendbootp.bp_xid = xid;
  71.     sendbootp.bp_secs = intel16( 1 );
  72.  
  73.     movmem( _eth_addr, &sendbootp.bp_chaddr, sizeof(eth_address));
  74.  
  75.     while ( 1 ) {
  76.   sock_fastwrite( &bsock, &sendbootp, sizeof( struct bootp ));
  77.         sendbootp.bp_secs = intel16( intel16( sendbootp.bp_secs ) + magictimeout );      /* for next time */
  78.         sendtimeout = set_timeout( magictimeout += (xid >> 5) & 7 );
  79.  
  80.         while ( !chk_timeout( sendtimeout )) {
  81.  
  82.             if (chk_timeout( bootptimeout))
  83.                 goto give_up;
  84.  
  85.             sock_tick( &bsock, &status );
  86.       if (len = sock_dataready( &bsock)) {
  87.  
  88.                 /* got a response, lets consider it */
  89.                 templen = sock_fastread( &bsock, &_bootp, sizeof( struct bootp ));
  90.                 if ( templen < sizeof( struct bootp )) {
  91.                     /* too small, not a bootp packet */
  92.         memset( &_bootp, 0, sizeof( struct bootp ));
  93.                     continue;
  94.                 }
  95.  
  96.                 /* we must see if this is for us */
  97.     if (_bootp.bp_xid != sendbootp.bp_xid) {
  98.         memset( &_bootp, 0, sizeof( struct bootp ));
  99.                     continue;
  100.                 }
  101.  
  102.                 /* we must have found it */
  103.     my_ip_addr = intel( _bootp.bp_yiaddr );
  104.  
  105.  
  106.     if ( intel( *(longword*)(&_bootp.bp_vend)) == VM_RFC1048 ) {
  107.         /*RFC1048 complient BOOTP vendor field */
  108.         /* Based heavily on NCSA Telnet BOOTP */
  109.  
  110.         p = &_bootp.bp_vend[4]; /* Point just after vendor field */
  111.  
  112.         while (*p!=255) {
  113.       switch(*p) {
  114.                           case 0: /* Nop Pad character */
  115.                                  p++;
  116.                                  break;
  117.                           case 1: /* Subnet Mask */
  118.          sin_mask = intel( *(longword *)( &p[2] ));
  119.          /* and fall through */
  120.         case 2: /* Time offset */
  121.          p += *(p+1) + 2;
  122.          break;
  123.         case 3: /* gateways */
  124.           /* only add first */
  125.           _arp_add_gateway( NULL,
  126.              intel( *(longword*)(&p[2])));
  127.           /* and fall through */
  128.         case 4: /*time servers */
  129.           /* fall through */
  130.                           case 5: /* IEN=116 name server */
  131.                                  p +=*(p+1)+2;
  132.                                  break;
  133.         case 6: /* Domain Name Servers (BIND) */
  134.         for ( len = 0; len < *(p+1) ; len += 4 )
  135.             _add_server( &_last_nameserver,
  136.           MAX_NAMESERVERS, def_nameservers,
  137.               intel( *(longword*)(&p[2+len])));
  138.         /* and fall through */
  139.         case 7: /* log server */
  140.          p += *(p+1)+2;
  141.          break;
  142.         case 8: /* cookie server */
  143.          for ( len = 0; len < *(p+1) ; len += 4 )
  144.              _add_server( &_last_cookie, MAX_COOKIES,
  145.           _cookie, intel( *(longword*)(&p[2+len])));
  146.          /* and fall through */
  147.                           case 9: /* lpr server */
  148.                           case 10: /* impress server */
  149.                           case 11: /* rlp server */
  150.            p +=*(p+1)+2;
  151.                                    break;
  152.         case 12: /* Client Hostname */
  153.           movmem( &p[2] , _hostname, MAX_STRING );
  154.           _hostname[ MAX_STRING - 1 ] = 0;
  155.           p += *(p+1)+2;
  156.                                   break;
  157.                           case 255:
  158.                                    break;
  159.                           default:
  160.                                    p +=*(p+1)+2;
  161.                                    break;
  162.                         } /* end of switch */
  163.                      } /* end of while */
  164.                 }/* end of RFC_1048 if */
  165.                 goto give_up;
  166.             }
  167.         }
  168.     }
  169. give_up:
  170.  
  171.     sock_close( &bsock );
  172.  
  173.     return (my_ip_addr == 0 );  /* return 0 on success */
  174.  
  175. sock_err:
  176.     /* major network error if UDP fails */
  177.     sock_close( &bsock );
  178.     return(ER_CONF);
  179. }
  180.