/*************************************************************************************** File: bootp.c Date: 7.10.2002 Version: 0.1 Author: Jari Lahti (jari@violasystems.com) Description: This file implements BOOT protocol client Version Info: 7.10.2002 - First version (Jari Lahti) ***************************************************************************************/ #include "opentcp.h" UINT8 bootpapp_init = 0; struct { UINT8 state; UINT8 mode; INT8 sochandle; UINT16 tmrhandle; UINT16 bootsecs; } Bootp; /******************************************************************************** Function: init_bootpc Parameters: UINT8 mode - 0: Do not save parameters permanently 1: Save parameters permanently Return val: INT8 - (>=0) OK (-1) Error Date: 7.19.2002 Desc: This function should be called before the BOOTP application is used to set the operating parameters of it *********************************************************************************/ INT8 init_bootpc (UINT8 mode) { /* Already initialized? */ if(bootpapp_init) return(1); /* Get socket handle */ Bootp.sochandle = udp_getsocket(0, bootpc_eventlistener, UDP_OPT_SEND_CS | UDP_OPT_CHECK_CS); if(Bootp.sochandle < 0) return(-1); /* Put it to listening mode */ if( udp_open(Bootp.sochandle, BOOTP_CLIENTPORT) < 0 ) return(-1); /* Get timer handle */ Bootp.tmrhandle = get_timer(); Bootp.bootsecs = 0; Bootp.mode = mode; Bootp.state = BOOTPC_STATE_DISABLED; bootpapp_init = 1; return(1); } /******************************************************************************** Function: bootpc_stop Parameters: void Return val: void Date: 9.10.2002 Desc: Closes the bootp *********************************************************************************/ void bootpc_stop (void) { if(bootpapp_init == 0) return; Bootp.state = BOOTPC_STATE_DISABLED; } /******************************************************************************** Function: bootpc_enable Parameters: void Return val: INT8 (-1) - Error (>=0) - OK Date: 9.10.2002 Desc: Enables the bootp *********************************************************************************/ INT8 bootpc_enable (void) { if(bootpapp_init == 0) return(-1); Bootp.state = BOOTPC_STATE_ENABLED; return(1); } /******************************************************************************** Function: bootpc_run Parameters: void Return val: void Date: 7.10.2002 Desc: The main thread of bootp that should be called periodically *********************************************************************************/ void bootpc_run (void) { INT16 i; /* State machine */ if(bootpapp_init == 0) return; switch(Bootp.state) { case BOOTPC_STATE_ENABLED: /* Check the IP address of the device and start BOOTP procedure for getting */ /* one if zero or 255.255.255.255 */ if( (localmachine.localip == 0) || (localmachine.localip == 0xFFFFFFFF) ) { /* We need to start BOOTP request procedure */ /* Firstly wait random time */ localmachine.localip = 0; localmachine.defgw = 0; localmachine.netmask = 0; init_timer(Bootp.tmrhandle, ((UINT32)(localmachine.localHW[0]) << 2) + localmachine.localHW[1]); Bootp.state = BOOTPC_STATE_REQUEST_NEEDED; } return; case BOOTPC_STATE_REQUEST_NEEDED: if( check_timer(Bootp.tmrhandle) != 0 ) return; /* Send request if we haven't get the IP in some other way */ if(localmachine.localip != 0) { Bootp.state = BOOTPC_STATE_ENABLED; return; } i = 0; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x01; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x01; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x06; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0xCA; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x03; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x32; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0xF1; OTCP_TXBUF[UDP_APP_OFFSET + i++] = (UINT8)(Bootp.bootsecs >> 8); OTCP_TXBUF[UDP_APP_OFFSET + i++] = (UINT8)Bootp.bootsecs; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x80; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 0x00; OTCP_TXBUF[UDP_APP_OFFSET + i++] = localmachine.localHW[5]; OTCP_TXBUF[UDP_APP_OFFSET + i++] = localmachine.localHW[4]; OTCP_TXBUF[UDP_APP_OFFSET + i++] = localmachine.localHW[3]; OTCP_TXBUF[UDP_APP_OFFSET + i++] = localmachine.localHW[2]; OTCP_TXBUF[UDP_APP_OFFSET + i++] = localmachine.localHW[1]; OTCP_TXBUF[UDP_APP_OFFSET + i++] = localmachine.localHW[0]; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 99; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 130; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 83; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 99; OTCP_TXBUF[UDP_APP_OFFSET + i++] = 255; for(i;i<300;i++) OTCP_TXBUF[UDP_APP_OFFSET + i] = 0; /* Send it */ udp_send(Bootp.sochandle, IP_BROADCAST_ADDRESS, BOOTP_SERVERPORT, &OTCP_TXBUF[UDP_APP_OFFSET], NETWORK_TX_BUFFER_SIZE - UDP_APP_OFFSET, 300); init_timer(Bootp.tmrhandle, BOOTP_RETRY_TOUT*TIMERTIC); Bootp.bootsecs += BOOTP_RETRY_TOUT*TIMERTIC; Bootp.state = BOOTPC_STATE_WAITING_REPLY; return; case BOOTPC_STATE_WAITING_REPLY: /* Wait untill timeout elapsed and try again */ if( check_timer(Bootp.tmrhandle) != 0 ) return; /* Try again */ Bootp.state = BOOTPC_STATE_REQUEST_NEEDED; return; case BOOTPC_STATE_REPLY_GET: /* You can save the parameters here to e.g. EEPROM */ Bootp.state = BOOTPC_STATE_ENABLED; return; default: return; } } INT32 bootpc_eventlistener (INT8 cbhandle, UINT8 event, UINT32 remip, UINT16 remport, UINT16 bufindex, UINT16 dlen) { INT16 i,j; UINT32 ip = 0; UINT32 nm = 0; UINT32 dgw = 0; UINT8 ch; /* This function is called by UDP stack to inform about events */ if(bootpapp_init == 0) return(-1); if( cbhandle != Bootp.sochandle) /* Not our handle */ return(-1); /* The only event is data */ if(Bootp.state != BOOTPC_STATE_WAITING_REPLY) return(-1); /* Process reply */ NETWORK_RECEIVE_INITIALIZE(bufindex); if(dlen < 300) return(-1); if( RECEIVE_NETWORK_B() != BOOTP_REPLY) return(-1); if( RECEIVE_NETWORK_B() != BOOTP_HTYPE_ETHERNET) return(-1); if( RECEIVE_NETWORK_B() != BOOTP_HWLEN_ETHERNET) return(-1); RECEIVE_NETWORK_B(); /* Skip hops */ /* Check transaction ID */ if( RECEIVE_NETWORK_B() != 0xCA) return(-1); if( RECEIVE_NETWORK_B() != 0x03) return(-1); if( RECEIVE_NETWORK_B() != 0x32) return(-1); if( RECEIVE_NETWORK_B() != 0xF1) return(-1); /* Skip elapsed, unused, client address */ for(i=0; i<8; i++) RECEIVE_NETWORK_B(); /* Get IP */ ip = RECEIVE_NETWORK_B(); ip <<= 8; ip |= RECEIVE_NETWORK_B(); ip <<= 8; ip |= RECEIVE_NETWORK_B(); ip <<= 8; ip |= RECEIVE_NETWORK_B(); /* Skip server ip & bootp router address */ for(i=0; i<8; i++) RECEIVE_NETWORK_B(); /* Check MAC */ if( RECEIVE_NETWORK_B() != localmachine.localHW[0]) return(-1); if( RECEIVE_NETWORK_B() != localmachine.localHW[1]) return(-1); if( RECEIVE_NETWORK_B() != localmachine.localHW[2]) return(-1); if( RECEIVE_NETWORK_B() != localmachine.localHW[3]) return(-1); if( RECEIVE_NETWORK_B() != localmachine.localHW[4]) return(-1); if( RECEIVE_NETWORK_B() != localmachine.localHW[5]) return(-1); RECEIVE_NETWORK_B(); RECEIVE_NETWORK_B(); for(i=0; i<200; i++) RECEIVE_NETWORK_B(); /* Check options */ dlen -= 236; i = 0; while(i= 2) { j -= 2; while(j--) { RECEIVE_NETWORK_B(); i++; } } continue; } if( ch == BOOTP_OPTION_SUBNETMASK) { RECEIVE_NETWORK_B(); /* Skip totlen */ nm = RECEIVE_NETWORK_B(); nm <<= 8; nm |= RECEIVE_NETWORK_B(); nm <<= 8; nm |= RECEIVE_NETWORK_B(); nm <<= 8; nm |= RECEIVE_NETWORK_B(); i += 5; } if( ch == BOOTP_OPTION_DEFGW) { j = RECEIVE_NETWORK_B(); /* Get totlen */ dgw = RECEIVE_NETWORK_B(); dgw <<= 8; dgw |= RECEIVE_NETWORK_B(); dgw <<= 8; dgw |= RECEIVE_NETWORK_B(); dgw <<= 8; dgw |= RECEIVE_NETWORK_B(); i += 5; /* Skip others */ if( j>5 ) { j -= 5; while(j--) { RECEIVE_NETWORK_B(); i++; } } } } /* Store parameters */ localmachine.localip = ip; localmachine.defgw = dgw; localmachine.netmask = nm; /* Change state */ Bootp.state = BOOTPC_STATE_REPLY_GET; return(1); }