⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dhcpc.c

📁 在freescale 的ne64上开发的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *Copyright (c) 2000-2002 Viola Systems Ltd.
 *All rights reserved.
 *
 *Redistribution and use in source and binary forms, with or without
 *modification, are permitted provided that the following conditions
 *are met:
 *
 *1. Redistributions of source code must retain the above copyright
 *notice, this list of conditions and the following disclaimer.
 *
 *2. Redistributions in binary form must reproduce the above copyright
 *notice, this list of conditions and the following disclaimer in the
 *documentation and/or other materials provided with the distribution.
 *
 *3. The end-user documentation included with the redistribution, if
 *any, must include the following acknowledgment:
 *	"This product includes software developed by Viola
 *	Systems (http://www.violasystems.com/)."
 *
 *Alternately, this acknowledgment may appear in the software itself,
 *if and wherever such third-party acknowledgments normally appear.
 *
 *4. The names "OpenTCP" and "Viola Systems" must not be used to
 *endorse or promote products derived from this software without prior
 *written permission. For written permission, please contact
 *opentcp@opentcp.org.
 *
 *5. Products derived from this software may not be called "OpenTCP",
 *nor may "OpenTCP" appear in their name, without prior written
 *permission of the Viola Systems Ltd.
 *
 *THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
 *WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *IN NO EVENT SHALL VIOLA SYSTEMS LTD. OR ITS CONTRIBUTORS BE LIABLE
 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 *WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 *OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 *EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *====================================================================
 *
 *OpenTCP is the unified open source TCP/IP stack available on a series
 *of 8/16-bit microcontrollers, please see <http://www.opentcp.org>.
 *
 *For more information on how to network-enable your devices, or how to
 *obtain commercial technical support for OpenTCP, please see
 *<http://www.violasystems.com/>.
 */

/** \file dhcpc.c
 *	\brief OpenTCP DHCP client implementation
 *	\author
 *		\li Vladan Jovanovic (vladan.jovanovic@violasystems.com)
 *	\version 1.03
 *	\date 23.5.2003
 *	\bug
 *	\warning
 *	\todo
 *		\li	We SHOULD first test (with PING or ARP) assigned IP
 *		address to see if it's in use already.
 *
 *	OpenTCP DHCP client protocol implementation. Features a complete
 * 	DHCP state machine. Function declarations can be found in dhcpc.h
 */

#include"datatypes.h"
#include"debug.h"
#include"system.h"
#include"tcp_ip.h"

#ifdef DHCPC_WANTED

#include"timers.h"
#include"dhcpc.h"

/** \brief Holds DHCP clients' state information
 *
 *	This variable holds DHCP clients' current state information. Possible
 *  states are DHCP_STATE_INIT_REBOOT, DHCP_STATE_REBOOTING,
 *	DHCP_STATE_INIT, DHCP_STATE_SELECTING, DHCP_STATE_REQUESTING,
 *	DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING.
 */
UINT8 dhcpc_state;

/** \brief DHCP client's timer handle
 *
 *	Hold DHCP clients' timer handle. We'll use only one timer from
 *	timer pool and take care of the rest by ourselves manually
 */
UINT8 dhcpc_timer_handle;

/** \brief DHCP client's UDP socket handle
 *
 *	DHCP client's UDP socket handle
 */
INT8 dhcpc_soc_handle;

/** \brief Holds information if DHCP client is initialized
 *
 *	Holds information if DHCP client is initialized
 */
UINT8	dhcpc_initialized=0;

/** \brief DHCP renew timer
 *
 *	This variable holds renew time (in seconds) after which we'll
 *  start the renewing process. While obtaining the parameters from
 * 	DHCP server (thus before we know of the renew time) this is
 *	used also to time retransmissions.
 */
UINT32 dhcpc_t1;

/** \brief DHCP rebind timer
 *
 *	This variable holds rebind time (in seconds) after which we'll
 *	start the rebinding process. While obtaining the paramters from
 * 	DHCP server (thus before we know of the renew time) this is
 *  also used to time retransmissions as well as timeout detection
 */
UINT32 dhcpc_t2;

/** \brief DHCP server identifier as received from DHCP server
 *
 *	This variable will hold DHCP server identifier (which will actually
 *	be server's IP address).
 */
UINT32 dhcpc_server_identifier;

/** \brief Holds offered IP address or IP address that we're requesting
 *
 *	This variable holds the IP address that DHCP server offered to us
 *	during address request procedure and this is the address that we
 *	will be requesting in all future requests untill DHCP server
 *	disallows us to use it any more.
 */
UINT32 dhcpc_requested_ip;

INT32 dhcpc_eventlistener(INT8 cbhandle, UINT8 event, UINT32 ipaddr, UINT16 port, UINT16 buffindex, UINT16 datalen);
INT8 dhcpc_send_message(UINT8 msg_type);

/** \brief Initializes DHCP client
 * 	\author
 *		\li Vladan Jovanovic (vladan.jovanovic@violasystems.com)
 *	\date 23.05.2003
 *
 *	This function should be called once when system starts to initialize
 *	and start DHCP client. Before this function is invoked,
 *	localmachine.localip MUST be se to either zero (in which case DHCP
 *	client will request any IP address) or a previously assigned IP
 *	address (which doesn't mean DHCP server will allow us to continue
 *	using this address) in which case DHCP client will first try to
 *	obtain that existing IP address.
 */
INT8 dhcpc_init(void)
{

	/* If we already have some IP address (stored from some previous
	 * requests, try obtaining it again */
	if((localmachine.localip!=0)&&(localmachine.localip!=0xffffffff)){
		dhcpc_state=DHCP_STATE_INIT_REBOOT;
	}else{
		/* start from beginning */
		dhcpc_state=DHCP_STATE_INIT;
		}

	dhcpc_soc_handle=udp_getsocket(0,dhcpc_eventlistener,UDP_OPT_SEND_CS|UDP_OPT_CHECK_CS);

	if(dhcpc_soc_handle<0){
		DEBUGOUT("DHCP client not able to obtain socket!\r\n");
		return (-1);
	}

	/* open socket for communication immediately */
	(void)udp_open(dhcpc_soc_handle,DHCP_CLIENT_PORT);

	/* get timer handle */
	dhcpc_timer_handle=get_timer();

	/* initialize timer for 1 sec intervals */
	init_timer(dhcpc_timer_handle,TIMERTIC*1);	/* on every second */

	dhcpc_initialized=1;
	DEBUGOUT("DHCP Client initialized\r\n");

	return (0);
}

/** \brief DHCP client main state machine
 * 	\author
 *		\li Vladan Jovanovic (vladan.jovanovic@violasystems.com)
 *	\date 23.05.2003
 *
 *	Call this function periodically from main loop to ensure
 *	proper operation. This function holds the main state machine
 *	of DHCP client that ensures proper operation.
 */
void dhcpc_run(void){
	UINT8 sec=0;

	if(!dhcpc_initialized)
		return;

	if(!check_timer(dhcpc_timer_handle))
		sec=1;

	switch(dhcpc_state){
		case DHCP_STATE_INIT_REBOOT:
			dhcpc_state=DHCP_STATE_REBOOTING;
			dhcpc_t1=4;	/* next retransmission in 4 secs */
			dhcpc_t2=8;	/* after that after 8 secs retrs */
			dhcpc_requested_ip=localmachine.localip;
			(void)dhcpc_send_message(DHCP_REQUEST);
			break;

		case DHCP_STATE_REBOOTING:
			if(sec)
				dhcpc_t1--;

			if(!dhcpc_t1){
				if(dhcpc_t2>=32){
					/* we need to restart, we don't want to wait more
					 * than 30 secs for retransmissions
					 */
					 dhcpc_state=DHCP_STATE_INIT_REBOOT;
				}else{
					dhcpc_t1=dhcpc_t2;
					dhcpc_t2<<=1;	/* exponential backoff retransmission */
					(void)dhcpc_send_message(DHCP_REQUEST);
				}
			}
			break;
		case DHCP_STATE_INIT:
			/* switch to selecting, send DHCPDISCOVER and initialize
			 * timeout timer
			 */
			DEBUGOUT("DHCP State=INIT; Sending DHCPDISCOVER message; State INIT-->SELECTING\r\n");
			dhcpc_state=DHCP_STATE_SELECTING;
			(void)dhcpc_send_message(DHCP_DISCOVER);
			/* T1 will be timeout timer. T2 will hold next timeout value */
			dhcpc_t1=4;	/* next retransmission after 4 secs */
			dhcpc_t2=8;	/* after 4 secs expire, this will be next timeout */
			break;
		case DHCP_STATE_SELECTING:
			/* one second expired ? */
			if(sec)
				dhcpc_t1--;

			/* timeout expired without receiving DHCPOFFER ? */
			if(!dhcpc_t1){
				DEBUGOUT("DHCP State=SELECTING; ");
				/* yes, retransmit or restart the process */
				if(dhcpc_t2>=32){
					/* we need to restart, we don't want to wait more
					 * than 30 secs for retransmissions
					 */
					 dhcpc_state=DHCP_STATE_INIT;
					 DEBUGOUT("Timeout for retransmissions too big; State SELECTING-->INIT\r\n");
				}else{
					DEBUGOUT("Retransmitting DHCPDISCOVER\r\n");
					dhcpc_t1=dhcpc_t2;
					dhcpc_t2<<=1;	/* exponential backoff retransmission */
					(void)dhcpc_send_message(DHCP_DISCOVER);
				}
			}
			break;
		case DHCP_STATE_REQUESTING:
			/* DHCPREQUEST sent, waiting for proper response. Retransmit
			 * if necessary
			 */
			if(sec)
			 	dhcpc_t1--;

			if(!dhcpc_t1){
				/* timeout occured without receiving DHCPACK */
				DEBUGOUT("DHCP State=REQUESTING; ");
				if(dhcpc_t2>=32){
					/* we need to restart, we don't want to wait more
					 * than 30 secs for retransmissions. Restart whole
					 * process
					 */
					 dhcpc_state=DHCP_STATE_INIT;
					 DEBUGOUT("Timeout for retransmits too big; State REQUESTING-->INIT\r\n");
				}else{
					DEBUGOUT("Retransmitting DHCPREQUEST\r\n");
					dhcpc_t1=dhcpc_t2;
					dhcpc_t2<<=1;	/* exponential backoff retransmission */
					(void)dhcpc_send_message(DHCP_REQUEST);
				}
			}
			break;
		case DHCP_STATE_BOUND:
			/* wait for T1 to expire */
			if(sec){
				dhcpc_t1--;
				dhcpc_t2--;
			}
			if(!dhcpc_t1){
				DEBUGOUT("DHCP State=BOUND; Starting renewing process; State BOUND-->RENEWING\r\n");
				/* T1 expired, start renewing process */
				dhcpc_state=DHCP_STATE_RENEWING;

				(void)dhcpc_send_message(DHCP_REQUEST);

				/* T1 will be used for retransmissions untill we
				 * return to BOUND state or reset to INIT state
				 */
				dhcpc_t1=10;	/* fixed 10sec retransmissions */
			}
			break;
		case DHCP_STATE_RENEWING:
			if(sec){
				dhcpc_t1--;
				dhcpc_t2--;
			}

			if(!dhcpc_t2){
				DEBUGOUT("DHCP State=RENEWING; T2 expired; State RENEWING-->REBINDING\r\n");
				/* oh no, T2 also expired. switch to rebinding state. This
				 * is our last attempt to retain this IP address.
				 */
				dhcpc_state=DHCP_STATE_REBINDING;

				(void)dhcpc_send_message(DHCP_REQUEST);

				/* dhcpc_t1 will be used for timeouts */
				dhcpc_t1=5;	/* 5 second retransmits */

				/* dhcpc_t2 will be used for fixed numer of retries. This
				 * is a bit different than per RFC, but we don't want
				 * another 32-bit timer value for keeping lease time.
				 */
				dhcpc_t2=10;
			}else
				if(!dhcpc_t1){
					DEBUGOUT("DHCP State=RENEWING; Retransmitting DHCPREQUEST\r\n");
					/* retransmit DHCP REQUEST messages */
					(void)dhcpc_send_message(DHCP_REQUEST);
					dhcpc_t1=10;
				}
			break;
		case DHCP_STATE_REBINDING:
			if(sec)
				dhcpc_t1--;

			if(!dhcpc_t1){

				dhcpc_t1=5;	/* 5 second retransmits */

				dhcpc_t2--;	/* retransmit count */

				if(!dhcpc_t2){
					DEBUGOUT("DHCP State=REBINDING; Lease time expired; State REBINDING-->INIT\r\n");
					/* used up retransmission. Assume that lease time
					 * expired by now. Restart the process
					 */
					 dhcpc_state=DHCP_STATE_INIT;
					 localmachine.localip=0;	/* can't use this any more */
				}else{
					DEBUGOUT("DHCP State=REBINDING; Retransmitting DHCPREQUEST\r\n");
					/* still have some time */
					(void)dhcpc_send_message(DHCP_REQUEST);
				}
			}
			break;
		default:
			break;
	}

	if(sec){
		init_timer(dhcpc_timer_handle,TIMERTIC*1);
	}
}

/** \brief Sends DHCP messages
 * 	\author
 *		\li Vladan Jovanovic (vladan.jovanovic@violasystems.com)
 *	\date 23.05.2003
 *	\param msg_type Type of DHCP message to be sent. This implementation
 *		can send only #DHCP_DISCOVER, #DHCP_REQUEST and #DCHP_DECLINE
 *		messages.
 *	\return Returns result of udp_send() function.
 *
 *	This is internal function invoked to send appropriate DHCP message.
 */
INT8 dhcpc_send_message(UINT8 msg_type)
{

	UINT16 index;
	UINT8 *buf_ptr;	/* transmit buffer pointer */

	/* first clear transmit buffer to all zeroes */
	for(index=UDP_APP_OFFSET;index<NETWORK_TX_BUFFER_SIZE;index++)
		net_buf[index]=0;

	buf_ptr=net_buf+UDP_APP_OFFSET;

	/* create DHCP message */

	*buf_ptr++=BOOT_REQUEST;
	*buf_ptr++=0x01;		/* htype=ethernet */
	*buf_ptr++=0x06;		/* hlen=6 for ethernet */
	*buf_ptr++=0x00;		/* hops=0 by clients */

	/* xid, use constant value for all requests (allowed by RFC) */
	*buf_ptr++=0xAA;
	*buf_ptr++=0xBB;
	*buf_ptr++=0xCC;
	*buf_ptr++=0xDD;

	/* seconds from boot. Fixed for now */
	*buf_ptr++=0x00;
	*buf_ptr++=0x00;

	/* flags, use broadcast */
	*buf_ptr++=0x80;
	*buf_ptr++=0x00;

	/* ciaddr. Sent only if client is in BOUND, RENEW or REBINDING
	 * state (RFC2131)
	 */
	if((dhcpc_state==DHCP_STATE_BOUND)
		||(dhcpc_state==DHCP_STATE_RENEWING)
		||(dhcpc_state==DHCP_STATE_REBINDING)){
		*buf_ptr++=(UINT8)(localmachine.localip>>24);
		*buf_ptr++=(UINT8)(localmachine.localip>>16);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -