blackchannel/POWERLINK/stacks/ip/ip_dhcp.c
/*********************************************************************************

  Function    : ip_dhcp_receive()
  Description : DHCP frame received, parse it and send reply to offer with request

  Parameter:
	hIp			: handle of used interface

*********************************************************************************/
Function    : ip_dhcp_receive()
Description : DHCP frame received, parse it and send reply to offer with request

hIp                     : handle of used interface
Function : ip_dhcp_receive () Description : DHCP frame received parse it and send reply to offer with request hIp : handle of used interface
void ip_dhcp_receive(IP_STACK_H hIp, eth_frame *pFrame, unsigned short ipHdrLen)
{
	struct in_addr	subnet,gateway,server,given;
	unsigned char	*pData;
	unsigned short	i,len,type=0,code;
	unsigned long	leaseTime, t1=0, t2=0, lval;
	ipHdrLen =  ipHdrLen + sizeof(udp_hdr);	
	pData = (unsigned char*)&pFrame->prot.ip + ipHdrLen;
	if(pData[0] != OPCODE_REPLY						
		||
		pData[2] != 6								
		||
		memcmp(pData+28, &hIp->local_eth_addr,6)	
		||
		pData[4] != hIp->state)						
	{
		return;
	}
	copy_ip_address(&given, pData + 16);
	if(given.S_un.S_addr == 0) return;		
	pData = pData + 236;
	if(memcmp(pData,MAGIC_COOKIE,4)) return;
	pData = pData + 4;	
	i = htons(pFrame->prot.ip.len) - ipHdrLen - 236;
	while(i--)
	{
		code = pData[0];		
		if(code == 0xFF) break;	
		len = pData[1];			
		pData = pData + 2;		
		#if LITTLE_ENDIAN==1
			((char*)&lval)[0] = ((char*)pData)[3];
			((char*)&lval)[1] = ((char*)pData)[2];
			((char*)&lval)[2] = ((char*)pData)[1];
			((char*)&lval)[3] = ((char*)pData)[0];
		#else
			((char*)&lval)[0] = ((char*)pData)[0];
			((char*)&lval)[1] = ((char*)pData)[1];
			((char*)&lval)[2] = ((char*)pData)[2];
			((char*)&lval)[3] = ((char*)pData)[3];
		#endif
		if(code==OPT_MESSAGE_TYPE && len==1) type = pData[0];				
		if(code==OPT_SERVER_IP    && len==4) memcpy(&server,pData,4);
		if(code==PAR_ID_ROUTERS   && len>=4) memcpy(&gateway,pData,4);
		if(type==MESSAGE_TYPE_ACK && len==4)	
		{
			if(code==PAR_ID_SUBNET)		memcpy(&subnet,pData,4);		
			if(code==OPT_LEASE_TIME)	leaseTime = lval;
			if(code==OPT_T1_RENEW)		t1 = lval;
			if(code==OPT_T2_REBIND)		t2 = lval;
		}
		pData = pData + len;	
	}
	if(type == MESSAGE_TYPE_NACK)
	{
		hIp->local_ip_addr.S_un.S_addr = 0;
		hIp->dhcp_given.S_un.S_addr    = 0;
		hIp->state = IP_STATE_DHCP_INIT;
	}
	else if(hIp->state == IP_STATE_DHCP_DISCOVER && type == MESSAGE_TYPE_OFFER)
	{
		if(given.S_un.S_addr > hIp->dhcp_given.S_un.S_addr)
		{
			hIp->dhcp_given.S_un.S_addr  = given.S_un.S_addr;
			hIp->dhcp_server.S_un.S_addr = server.S_un.S_addr;
		}
	}
	else if((hIp->state == IP_STATE_DHCP_REQUEST || hIp->state == IP_STATE_DHCP_RENEWING || hIp->state == IP_STATE_DHCP_REBIND)
		&& type == MESSAGE_TYPE_ACK)
	{
		hIp->local_ip_addr.S_un.S_addr = hIp->dhcp_given.S_un.S_addr;
		ipSetGateway(hIp, &subnet,&gateway);
		if(t1 == 0) t1 = leaseTime / 2;
		if(t2 == 0) t2 = (leaseTime / 4)*3;
		hIp->dhcp_t1	= hIp->time_s + t1;
		hIp->dhcp_t2	= hIp->time_s + t2;
		hIp->dhcp_lease	= hIp->time_s + leaseTime;
		if(hIp->dhcp_t1    < hIp->time_s) hIp->dhcp_t1    = 0xFFFFFFFF;
		if(hIp->dhcp_t2    < hIp->time_s) hIp->dhcp_t2    = 0xFFFFFFFF;
		if(hIp->dhcp_lease < hIp->time_s) hIp->dhcp_lease = 0xFFFFFFFF;
		hIp->state		= IP_STATE_OK;
	}
}
void ip_dhcp_receive ( IP_STACK_H hIp , eth_frame * pFrame , unsigned short ipHdrLen ) { struct in_addr subnet , gateway , server , given ; unsigned char * pData ; unsigned short i , len , type = 0 , code ; unsigned long leaseTime , t1 = 0 , t2 = 0 , lval ; ipHdrLen = ipHdrLen + sizeof ( udp_hdr ) ; pData = ( unsigned char * ) & pFrame -> prot . ip + ipHdrLen ; if ( pData [ 0 ] != OPCODE_REPLY || pData [ 2 ] != 6 || memcmp ( pData + 28 , & hIp -> local_eth_addr , 6 ) || pData [ 4 ] != hIp -> state ) { return ; } copy_ip_address ( & given , pData + 16 ) ; if ( given . S_un . S_addr == 0 ) return ; pData = pData + 236 ; if ( memcmp ( pData , MAGIC_COOKIE , 4 ) ) return ; pData = pData + 4 ; i = htons ( pFrame -> prot . ip . len ) - ipHdrLen - 236 ; while ( i -- ) { code = pData [ 0 ] ; if ( code == 0xFF ) break ; len = pData [ 1 ] ; pData = pData + 2 ; #if LITTLE_ENDIAN == 1 ( ( char * ) & lval ) [ 0 ] = ( ( char * ) pData ) [ 3 ] ; ( ( char * ) & lval ) [ 1 ] = ( ( char * ) pData ) [ 2 ] ; ( ( char * ) & lval ) [ 2 ] = ( ( char * ) pData ) [ 1 ] ; ( ( char * ) & lval ) [ 3 ] = ( ( char * ) pData ) [ 0 ] ; #else ( ( char * ) & lval ) [ 0 ] = ( ( char * ) pData ) [ 0 ] ; ( ( char * ) & lval ) [ 1 ] = ( ( char * ) pData ) [ 1 ] ; ( ( char * ) & lval ) [ 2 ] = ( ( char * ) pData ) [ 2 ] ; ( ( char * ) & lval ) [ 3 ] = ( ( char * ) pData ) [ 3 ] ; #endif if ( code == OPT_MESSAGE_TYPE && len == 1 ) type = pData [ 0 ] ; if ( code == OPT_SERVER_IP && len == 4 ) memcpy ( & server , pData , 4 ) ; if ( code == PAR_ID_ROUTERS && len >= 4 ) memcpy ( & gateway , pData , 4 ) ; if ( type == MESSAGE_TYPE_ACK && len == 4 ) { if ( code == PAR_ID_SUBNET ) memcpy ( & subnet , pData , 4 ) ; if ( code == OPT_LEASE_TIME ) leaseTime = lval ; if ( code == OPT_T1_RENEW ) t1 = lval ; if ( code == OPT_T2_REBIND ) t2 = lval ; } pData = pData + len ; } if ( type == MESSAGE_TYPE_NACK ) { hIp -> local_ip_addr . S_un . S_addr = 0 ; hIp -> dhcp_given . S_un . S_addr = 0 ; hIp -> state = IP_STATE_DHCP_INIT ; } else if ( hIp -> state == IP_STATE_DHCP_DISCOVER && type == MESSAGE_TYPE_OFFER ) { if ( given . S_un . S_addr > hIp -> dhcp_given . S_un . S_addr ) { hIp -> dhcp_given . S_un . S_addr = given . S_un . S_addr ; hIp -> dhcp_server . S_un . S_addr = server . S_un . S_addr ; } } else if ( ( hIp -> state == IP_STATE_DHCP_REQUEST || hIp -> state == IP_STATE_DHCP_RENEWING || hIp -> state == IP_STATE_DHCP_REBIND ) && type == MESSAGE_TYPE_ACK ) { hIp -> local_ip_addr . S_un . S_addr = hIp -> dhcp_given . S_un . S_addr ; ipSetGateway ( hIp , & subnet , & gateway ) ; if ( t1 == 0 ) t1 = leaseTime / 2 ; if ( t2 == 0 ) t2 = ( leaseTime / 4 ) * 3 ; hIp -> dhcp_t1 = hIp -> time_s + t1 ; hIp -> dhcp_t2 = hIp -> time_s + t2 ; hIp -> dhcp_lease = hIp -> time_s + leaseTime ; if ( hIp -> dhcp_t1 < hIp -> time_s ) hIp -> dhcp_t1 = 0xFFFFFFFF ; if ( hIp -> dhcp_t2 < hIp -> time_s ) hIp -> dhcp_t2 = 0xFFFFFFFF ; if ( hIp -> dhcp_lease < hIp -> time_s ) hIp -> dhcp_lease = 0xFFFFFFFF ; hIp -> state = IP_STATE_OK ; } }
Function    : ip_dhcp_receive()
Description : DHCP frame received, parse it and send reply to offer with request
Function : ip_dhcp_receive () Description : DHCP frame received parse it and send reply to offer with request
// add udp header to header variable // not a reply // not a 6 byte HW address // compare hw address // compare transaction ID // get given ip address // no IP address given // access to option field // get option code // exit loop if option end was found // get number of following bytes // set ptr to option data // get message type // overtake subnet and gateway from ACK // subnet mask // set ptr to next option // offer received // store given address and server address if the ip address is higher than the ones received until now // ack received	 // overtake ip address, subnetmask and gateway // check for timer overflows (very large values for r1,t2 and lease (infinite))