home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / CEREBRUM / WAT9609.ZIP / SRC / PCBOOTP.C < prev    next >
Text File  |  1994-11-28  |  7KB  |  198 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.3 : Feb  1, 1992 : J. Dent - patched up various things
  11.  *   0.2 : May 22, 1991 : E.J. Sutcliffe - added RFC_1048 vendor fields
  12.  *   0.1 : May  9, 1991 : E. Engelke - made part of the library
  13.  *   0.0 : May  3, 1991 : E. Engelke - original program as an application
  14.  *
  15.  */
  16.  
  17. #include <copyright.h>
  18. #include <stdio.h>
  19. #include <wattcp.h>
  20. #include <mem.h>
  21. #include <bootp.h>
  22. #include <conio.h>
  23.  
  24. /* global variables */
  25. longword _bootphost = 0xffffffffL;
  26. word _bootptimeout = 30;
  27. word _bootpon = 0;
  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( void )
  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( -1 );
  49.  
  50.  
  51.     /* We must get Waterloo TCP to use IP address 0 for sending */
  52.     xid = my_ip_addr;   /* a unique value coming from the ethernet card */
  53.     my_ip_addr = 0;
  54.  
  55.     if (!udp_open( &bsock, IPPORT_BOOTPC, _bootphost, IPPORT_BOOTPS, NULL )) {
  56.         outs("\n\rUnable to resolve bootp server\n\r");
  57.         return( -1 );
  58.     }
  59.  
  60.     bootptimeout = set_timeout( _bootptimeout );
  61.     magictimeout = (xid & 7) + 7;  /* between 7 and 14 seconds */
  62.  
  63.     memset( &sendbootp, 0, sizeof( struct bootp ));
  64.     sendbootp.bp_op = BOOTREQUEST;
  65.     sendbootp.bp_htype = _pktdevclass;
  66.     /* Copy into position the Magic Number used by Bootp */
  67.     /* avoid static storage and pushf/call assembler instructions */
  68.     *(longword *)(&sendbootp.bp_vend) = intel(VM_RFC1048);
  69.  
  70.     if (_pktdevclass == PD_ETHER) sendbootp.bp_hlen = 6;
  71.  
  72.     sendbootp.bp_xid = xid;
  73.     sendbootp.bp_secs = intel16( 1 );
  74.  
  75. //    movmem( &_eth_addr, &sendbootp.bp_chaddr, sizeof(eth_address));
  76. // 94.11.19 ??
  77.     movmem( &_eth_addr, sendbootp.bp_chaddr, sizeof(eth_address));
  78.  
  79.     while ( 1 ) {
  80.     sock_fastwrite( (sock_type*)&bsock, (byte *)&sendbootp, sizeof( struct bootp ));
  81.         sendbootp.bp_secs = intel16( intel16( sendbootp.bp_secs ) + magictimeout );      /* for next time */
  82.         sendtimeout = set_timeout( magictimeout += (xid >> 5) & 7 );
  83.  
  84.         while ( !chk_timeout( sendtimeout )) {
  85.  
  86.             if (chk_timeout( bootptimeout))
  87.                 goto give_up;
  88.             kbhit();
  89.         sock_tick( (sock_type*)&bsock, &status );
  90.             status = status;    /* get rid of warning */
  91.         if ((len = sock_dataready( (sock_type*)&bsock)) != 0 ) {
  92.  
  93.                 /* got a response, lets consider it */
  94.         templen = sock_fastread( (sock_type*)&bsock, (byte *)&_bootp, sizeof( struct bootp ));
  95.                 if ( templen < sizeof( struct bootp )) {
  96.                     /* too small, not a bootp packet */
  97.             memset( &_bootp, 0, sizeof( struct bootp ));
  98.                     continue;
  99.                 }
  100.  
  101.                 /* we must see if this is for us */
  102.         if (_bootp.bp_xid != sendbootp.bp_xid) {
  103.             memset( &_bootp, 0, sizeof( struct bootp ));
  104.                     continue;
  105.                 }
  106.  
  107.                 /* we must have found it */
  108.         my_ip_addr = intel( _bootp.bp_yiaddr );
  109.  
  110.  
  111.         if ( intel( *(longword*)(&_bootp.bp_vend)) == VM_RFC1048 ) {
  112.             /*RFC1048 complient BOOTP vendor field */
  113.             /* Based heavily on NCSA Telnet BOOTP */
  114.  
  115.             p = &_bootp.bp_vend[4]; /* Point just after vendor field */
  116.  
  117.                     while ((*p!=255) && (p <= &_bootp.bp_vend[63])) {
  118.             switch(*p) {
  119.                           case 0: /* Nop Pad character */
  120.                                  p++;
  121.                                  break;
  122.                           case 1: /* Subnet Mask */
  123.                  sin_mask = intel( *(longword *)( &p[2] ));
  124.                  /* and fall through */
  125.               case 2: /* Time offset */
  126.                  p += *(p+1) + 2;
  127.                  break;
  128.               case 3: /* gateways */
  129.                   /* only add first */
  130.                   _arp_add_gateway( NULL,
  131.                      intel( *(longword*)(&p[2])));
  132.                                   p +=*(p+1)+2;
  133.                                   break;
  134.                   /* and fall through */
  135.               case 4: /*time servers */
  136.                   /* fall through */
  137.                           case 5: /* IEN=116 name server */
  138.                                  p +=*(p+1)+2;
  139.                                  break;
  140.               case 6: /* Domain Name Servers (BIND) */
  141.                 for ( len = 0; len < *(p+1) ; len += 4 )
  142.                     _add_server( &_last_nameserver,
  143.                     MAX_NAMESERVERS, def_nameservers,
  144.                         intel( *(longword*)(&p[2+len])));
  145.                 /* and fall through */
  146.               case 7: /* log server */
  147.                  p += *(p+1)+2;
  148.                  break;
  149.               case 8: /* cookie server */
  150.                  for ( len = 0; len < *(p+1) ; len += 4 )
  151.                      _add_server( &_last_cookie, MAX_COOKIES,
  152.                     _cookie, intel( *(longword*)(&p[2+len])));
  153.                                   /* and fall through */
  154.                                   p +=*(p+1)+2;
  155.                                   break;
  156.                           case 9: /* lpr server */
  157.                           case 10: /* impress server */
  158.                           case 11: /* rlp server */
  159.                                    p +=*(p+1)+2;
  160.                                    break;
  161.               case 12: /* Client Hostname */
  162.                   movmem( &p[2] , _hostname, MAX_STRING );
  163.                                 /* bootpfix - 94.09.30 mdurkin@tsoft.net */
  164.                        /* hostname field is *not* null terminated; need to use
  165.                             length byte.  Extra bytes used to be tacked on the
  166.                             end, usually just a single 0xFF char (the end tag).
  167.                             Technically should also probably make the
  168.                             _hostname buffer 256 chars long so we'll never
  169.                             truncate the name arbitrarily... see CMU bootpd. */
  170.                                   if( *(p+1) < MAX_STRING ) {
  171.                                       _hostname[ *(p+1) ] = '\0';
  172.                                   } else _hostname[ MAX_STRING - 1 ] = '\0';
  173.                   p += *(p+1)+2;
  174.                                   break;
  175.                           case 255:
  176.                                    break;
  177.                           default:
  178.                                    p +=*(p+1)+2;
  179.                                    break;
  180.                         } /* end of switch */
  181.                      } /* end of while */
  182.                 }/* end of RFC_1048 if */
  183.                 goto give_up;
  184.             }
  185.         }
  186.     }
  187. give_up:
  188.  
  189.     sock_close( (sock_type *)&bsock );
  190.  
  191.     return (my_ip_addr == 0 );  /* return 0 on success */
  192.  
  193. sock_err:
  194.     /* major network error if UDP fails */
  195.     sock_close( (sock_type *)&bsock );
  196.     return( -1 );
  197. }
  198.