/* * * BOOTP - Boot Protocol (RFC 854) * * These extensions get called if _bootphost is set to an IP address or * to 0xffffffff. * * Version * * 0.1 : May 9, 1991 : E. Engelke - made part of the library * 0.0 : May 3, 1991 : E. Engelke - original program as an application * */ #include #include #include #include /* global variables */ longword _bootphost = 0L; word _bootptimeout = 30; extern longword set_timeout(); /* * _dobootpc - Checks global variables _bootptimeout, _bootphost * if no host specified, the broadcast address * returns 0 on success and sets ip address */ int _dobootp() { udp_Socket bsock; longword sendtimeout, bootptimeout; word magictimeout; word len, templen; struct bootp sendbootp; /* outgoing data */ struct bootp _bootp; /* incoming data */ int found; int status; longword xid; if ( _pktdevclass == PD_SLIP ) return( -1 ); found = 0; /* We must get Waterloo TCP to use IP address 0 for sending */ xid = my_ip_addr; /* a unique value coming from the ethernet card */ my_ip_addr = 0; if (!udp_Open( &bsock, IPPORT_BOOTPC, _bootphost, IPPORT_BOOTPS, NULL )) { outs("\n\rUnable to resolve bootp server\n\r"); return( -1 ); } bootptimeout = set_timeout( _bootptimeout ); magictimeout = (xid & 7) + 7; /* between 7 and 14 seconds */ memset( &sendbootp, 0, sizeof( struct bootp )); sendbootp.bp_op = BOOTREQUEST; sendbootp.bp_htype = _pktdevclass; if (_pktdevclass == PD_ETHER) sendbootp.bp_hlen = 6; sendbootp.bp_xid = xid; sendbootp.bp_secs = intel16( 1 ); movmem( _eth_addr, &sendbootp.bp_chaddr, sizeof(eth_address)); while ( 1 ) { sock_FastWrite( &bsock, &sendbootp, sizeof( struct bootp )); sendbootp.bp_secs += magictimeout; /* for next time */ sendtimeout = set_timeout( magictimeout += (xid > 5) & 7 ); while ( !chk_timeout( sendtimeout )) { if (chk_timeout( bootptimeout)) goto give_up; sock_tick( &bsock, &status ); if (len = sock_DataReady( &bsock)) { /* got a response, lets consider it */ templen = sock_FastRead( &bsock, &_bootp, sizeof( struct bootp )); if ( len < sizeof( struct bootp )) { /* too small, not a bootp packet */ memset( _bootp, 0, sizeof( struct bootp )); continue; } /* we must see if this is for us */ if (_bootp.bp_xid != sendbootp.bp_xid) { outs("Got someone else's xid "); continue; } /* we must have found it */ my_ip_addr = intel( _bootp.bp_yiaddr ); _bootphost = intel( _bootp.bp_siaddr ); if (!sin_gate) sin_gate = intel( _bootp.bp_giaddr ); goto give_up; } } } give_up: sock_Close( &bsock ); return (my_ip_addr == 0 ); /* return 0 on success */ sock_err: /* major network error if UDP fails */ sock_Close( &bsock ); return( -1 ); }