现在的位置: 首页 > 综合 > 正文

DHCP客户端实现(初稿)

2013年10月08日 ⁄ 综合 ⁄ 共 10979字 ⁄ 字号 评论关闭

 

 include "DHCP.h"

 #define _DHCP_C
 #define THIS_IS_DHCP

 #define DHCP_TIMEOUT                    (TICK)(2L * TICK_SECOND)


#define DHCP_CLIENT_PORT                (68u)
#define DHCP_SERVER_PORT                (67u)

#define BOOT_REQUEST                    (1u)
#define BOOT_REPLY                      (2u)
#define HW_TYPE                         (1u)
#define LEN_OF_HW_TYPE                  (6u)

#define DHCP_MESSAGE_TYPE               (53u)
#define DHCP_MESSAGE_TYPE_LEN           (1u)

#define DHCP_UNKNOWN_MESSAGE            (0u)

#define DHCP_DISCOVER_MESSAGE           (1u)
#define DHCP_OFFER_MESSAGE              (2u)
#define DHCP_REQUEST_MESSAGE            (3u)
#define DHCP_DECLINE_MESSAGE            (4u)
#define DHCP_ACK_MESSAGE                (5u)
#define DHCP_NAK_MESSAGE                (6u)
#define DHCP_RELEASE_MESSAGE            (7u)

#define DHCP_SERVER_IDENTIFIER          (54u)
#define DHCP_SERVER_IDENTIFIER_LEN      (4u)

#define DHCP_PARAM_REQUEST_LIST         (55u)
#define DHCP_PARAM_REQUEST_LIST_LEN     (2u)
#define DHCP_PARAM_REQUEST_IP_ADDRESS       (50u)
#define DHCP_PARAM_REQUEST_IP_ADDRESS_LEN   (4u)
#define DHCP_SUBNET_MASK                (1u)
#define DHCP_ROUTER                     (3u)
#define DHCP_IP_LEASE_TIME              (51u)
#define DHCP_END_OPTION                 (255u)

#define HALF_HOUR                       (WORD)((WORD)60 * (WORD)30)

#define INVALID_UDP_SOCKET      (0xff)
#define INVALID_UDP_PORT        (0L)

#define SIZE_OF_DHCPMES   (548u)   //标准DHCP报文字节大小

DHCP_MES DHCPMes;
APP_CONFIG AppConfig;

SM_DHCP  smDHCPState = SM_DHCP_INIT;
static UDP_SOCKET DHCPSocket = INVALID_UDP_SOCKET;


DHCP_STATE DHCPState = { 0x00 };

static IP_ADDR DHCPServerID;
//static DWORD_VAL DHCPLeaseTime;

static IP_ADDR tempIPAddress;
static IP_ADDR tempGateway;
static IP_ADDR tempMask;

INT8U SizeOfOptionsUsed;    //DHCP报文options字段使用的字节
INT8U SizeOfDHCPMesUsed;	//DHCP报文全部字段使用字节长度


static INT8U _DHCPReceive(void);
static void _DHCPSend(INT8U messageType);

 /*
*********************************************************************************************************
*                                            DHCPReset
*
* Description: 对DHCP进行重置,设置相应的参数
*												
* Arguments  : void
*									
* Returns    : void 
*
* Notes		 : 当服务器发回NAC报文时调用此函数			
*
**********************************************************************************************************
*/
void DHCPReset(void)
{
    // Do not reset DHCP if it was previously disabled.
    if ( smDHCPState == SM_DHCP_DISABLED )
        return;

    if ( DHCPSocket != INVALID_UDP_SOCKET )
        UDPClose(DHCPSocket);				 //???????????关闭套接字
    DHCPSocket = INVALID_UDP_SOCKET;

    smDHCPState = SM_DHCP_INIT;
//    DHCPBindCount = 0;

    DHCPState.bits.bIsBound = FALSE;
}

 /*
*********************************************************************************************************
*                                            DHCP_MesInit
*
* Description: DHCP报文初始化函数:对除了options字段外其他部分进行初始化,供DHCP_Send函数进行调用
*												
* Arguments  : void
*									
* Returns    : void 
*
* Notes		 : 报文部分字段赋值为固定值			
*
**********************************************************************************************************
*/
viod DHCP_MesInit(viod)
{
  INT8U i;

  DHCPMes.op=BOOT_REQUEST;
  DHCPMes.htype=HW_TYPE;
  DHCPMes.hlen=LEN_OF_HW_TYPE;
  DHCPMes.hops=0;
  DHCPMes.xid[0]=0x12;
  DHCPMes.xid[1]=0x34;
  DHCPMes.xid[2]=0x56;
  DHCPMes.xid[3]=0x78;
  DHCPMes.secs[0]=0;
  DHCPMes.secs[1]=0;
  DHCPMes.flags[0]=0x80;
  DHCPMes.flags[1]=0;
  for(i=0;i<4u;i++)
  {
    DHCPMes.ciaddr[i]=0x00;
	DHCPMes.yiaddr[i]=0x00;
	DHCPMes.siaddr[i]=0x00;
	DHCPMes.giaddr[i]=0x00;
  }
  DHCPMes.chaddr[0]=AppConfig.MyMACAddr.v[0];
  DHCPMes.chaddr[1]=AppConfig.MyMACAddr.v[1];
  DHCPMes.chaddr[2]=AppConfig.MyMACAddr.v[2];
  DHCPMes.chaddr[3]=AppConfig.MyMACAddr.v[3];
  DHCPMes.chaddr[4]=AppConfig.MyMACAddr.v[4];
  DHCPMes.chaddr[5]=AppConfig.MyMACAddr.v[5];
  for(i=6;i<16u;i++) 
  {
    DHCPMes.chaddr[i]=0x00;
  }
  for(i=0;i<64u;i++) 
  {
    DHCPMes.sname[i]=0x00;
  }
  for(i=0;i<128u;i++)
  {
    DHCPMes.file[i]=0x00;
  } 
}
/*   end of DHCP_MesInit  */

 /*
*********************************************************************************************************
*                                            DHCP_Task
*
* Description: DHCP主任务模块,获取IP、子网掩码、默认网关 ,并存放在全局变量结构体AppConfig中,是DHCP任务核心函数
*												
* Arguments  : void
*									
* Returns    : void 
*
* Notes		 : 租期未考虑			
*
**********************************************************************************************************
*/
viod DHCP_Task(viod)
{
    INT8U DHCPReValue;


	switch(smDHCPState)
	{
	    case SM_DHCP_INIT:
		   tempIPAddress.val=0x0;
//		   DHCP_MesInit();
		   DHCPSocket=Socket_Create();    //?????????创建
		   smDHCPState=SM_DHCP_BROADCAST;
		   /* No break */
		case SM_DHCP_BROADCAST:
		   
		   if(DHCPState.bits.bIsBound)  smDHCPState=SM_DHCP_REQUEST;
		   else if( UDPIsPutReady(DHCPSocket) )	                 //???????????????????
		   {
		     	DHCP_Send(DHCP_DISCOVER_MESSAGE);
				smDHCPState=SM_DHCP_DISCOVER;
		   }
		   break;
		case SM_DHCP_DISCOVER:
		     if ( UDPIsGetReady(DHCPSocket) )	 //????????????????????????
			 {
			     if(DHCP_Receive()==DHCP_OFFER_MESSAGE)
				   {
				      smDHCPState=SM_DHCP_REQUEST;
				   }
				 else break;
			 }
			 else break;
		 case SM_DHCP_REQUEST:
		      if( UDPIsPutReady(DHCPSocket) )		   //???????套接字连接 成功
			  {
			      DHCP_Send(DHCP_REQUEST_MESSAGE);
				  smDHCPState=SM_DHCP_BIND;
			  }
			  else break;
		 case SM_DHCP_BIND:
		       if(UDPIsGetReady(DHCPSocket))	 //??????????????????????
			   {
			      DHCPReValue=DHCP_Receive();
			       if(DHCPReValue==DHCP_NAK_MESSAGE)
				   {
				      DHCP_Reset();
					  return;
				   }
				   else if(DHCPReValue==DHCP_ACK_MESSAGE)
				   {
				       UDPClose(DHCPSocket);   //???????????
                       DHCPSocket = INVALID_UDP_SOCKET;
					   AppConfig.MyIPAddr=tempIPAddress;
					   AppConfig.MyMask=tempMask;
					   AppConfig.MyGateway=tempGateway;
					   return;
				   } 
			   }
			   break;
	}/* end of switch*/
}/*end of DHCP_Task*/
											   

 /*
*********************************************************************************************************
*                                            DHCP_Send
*
* Description: DHCP发送报文函数,根据传入的报文类型,产生相应的报文并发送
*												
* Arguments  : INT8U messageType 报文类型	 DHCP_DISCOVER_MESSAGE或DHCP_REQUEST_MESSAGE
*									
* Returns    : void 
*
* Notes		 : 租期未考虑			
*
**********************************************************************************************************
*/
void DHCP_Send(INT8U messageType)
{
   DHCP_MesInit();
   INT8U n=0;
   //options字段开始标志
   DHCPMes.options[n++]=99;
   DHCPMes.options[n++]=130;
   DHCPMes.options[n++]=83;
   DHCPMes.options[n++]=99;

   //设置options 53字段(报文类型信息)
   DHCPMes.options[n++]=DHCP_MESSAGE_TYPE;
   DHCPMes.options[n++]=DHCP_MESSAGE_TYPE_LEN;
   DHCPMes.options[n++]=messageType;

      if(messageType==DHCP_DISCOVER_MESSAGE)
       {
      	 DHCPState.bits.bIsBound=FALSE;
       }

      if(messageType!=DHCP_DISCOVER_MESSAGE&&tempIPAddress.Val!=0x0000u)
       {
         DHCPMes.options[n++]=DHCP_SERVER_IDENTIFIER;
		 DHCPMes.options[n++]=DHCP_SERVER_IDENTIFIER_LEN;
		 DHCPMes.options[n++]=DHCPServerID.v[0];
		 DHCPMes.options[n++]=DHCPServerID.v[1];
		 DHCPMes.options[n++]=DHCPServerID.v[2];
		 DHCPMes.options[n++]=DHCPServerID.v[3];
        }

   //请求队列(子网掩码和默认网关)
   DHCPMes.options[n++]=DHCP_PARAM_REQUEST_LIST;
   DHCPMes.options[n++]=DHCP_PARAM_REQUEST_LIST_LEN;
   DHCPMes.options[n++]=DHCP_SUBNET_MASK;
   DHCPMes.options[n++]=DHCP_ROUTER;
       
	   if(messageType==DHCP_REQUEST_MESSAGE)
	    {
		  DHCPMes.options[n++]=DHCP_PARAM_REQUEST_IP_ADDRESS;
		  DHCPMes.options[n++]=DHCP_PARAM_REQUEST_IP_ADDRESS_LEN;
		  
		  DHCPMes.options[n++]=tempIPAddress.v[0];
		  DHCPMes.options[n++]=tempIPAddress.v[1];
		  DHCPMes.options[n++]=tempIPAddress.v[2];
		  DHCPMes.options[n++]=tempIPAddress.v[3];

		}
	DHCPMes.options[n++] = DHCP_END_OPTION;   //options字段结束标志位
	SizeOfOptionsUsed=n+1;
	SizeOfDHCPMesUsed=SizeOfOptionsUsed+236;


	/*   
	  转换mbuf 数组结构,调用 socket 发送报文  代写。。。。。。。。。
	  
	   */





}//end of DHCP_Send()

/*********************************************************************
        DHCP PACKET FORMAT AS PER RFC 1541

   0                   1                   2                   3
   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
   +---------------+---------------+---------------+---------------+
   |                            xid (4)                            |
   +-------------------------------+-------------------------------+
   |           secs (2)            |           flags (2)           |
   +-------------------------------+-------------------------------+
   |                          ciaddr  (4)                          |
   +---------------------------------------------------------------+
   |                          yiaddr  (4)                          |
   +---------------------------------------------------------------+
   |                          siaddr  (4)                          |
   +---------------------------------------------------------------+
   |                          giaddr  (4)                          |
   +---------------------------------------------------------------+
   |                                                               |
   |                          chaddr  (16)                         |
   |                                                               |
   |                                                               |
   +---------------------------------------------------------------+
   |                                                               |
   |                          sname   (64)                         |
   +---------------------------------------------------------------+
   |                                                               |
   |                          file    (128)                        |
   +---------------------------------------------------------------+
   |                                                               |
   |                          options (312)                        |
   +---------------------------------------------------------------+

 ********************************************************************/
 /*
*********************************************************************************************************
*                                            DHCP_Receive
*
* Description: 将接收到的报文的有效信息进行提取,并存放于全局变量的结构体
*												
* Arguments  : void
*									
* Returns    : (INT8U) type 报文类型 
*
* Notes		 : 租期未考虑			
*
**********************************************************************************************************
*/
 static INT8U DHCP_Receive(void)
 {
    
	   /*
		  ???????????/mbf数据数组 转化成DHCP报文(DHCPMes)```````````

	   */
	  INT8U type,i,j;
	  INT8U s=0;
	  BOOL lbDone;
	  IP_ADDR tempServerID;

	  type=DHCP_UNKNOWN_MESSAGE;
	  //make sure that the message comes from server
	  if(DHCPMes.op=BOOT_REPLY)
	  {
  		   if(!DHCPState.bits.bOffereReceived)	//之前没有获得offer报文
		   {
		       tempIPAddress.Val=DHCPMes.yiaddr.Val;	   //将客户端被提供的IP存入teamIPAddress中
		   }
		   
		   // Check to see if chaddr (Client Hardware Address) belongs to us.
		   for(i=0;i<6u;i++)
		   {
 		     if(DHCPMes.chaddr.v[i] != AppConfig.MyMACAddr.v[i])
			 goto UDPInvalid; 
		   }

		   lbDone = FALSE;
		   do
            {
			   //Get the Option number
			   switch(DHCPMes.options[s])
                          case DHCP_MESSAGE_TYPE:
						               s++	;
									   if(DHCPMes.options[s++]==1u)
									   {
									  //    s++;
										        type=DHCPMes.options[s++];
										        if(DHCPState.bits.bOfferReceived&&(type==DHCP_OFFER_MESSAGE)) //throw another offer when we already have one
										        {
										              goto UDPInvalid;
										        }
									   }
									   else goto UDPInvalid;
						  break;

						  case DHCP_SUBNET_MASK:
						               s++;
									   if(DHCPMes.options[s++]==4u)
									   {
									           	 if(!DHCPState.bits.bOfferReceived)	// Check to see if this is the first offer
												 {
												      	for(i=0;i<4;i++)
														{
														   tempMask[i]=DHCPMes.options[s++];  //将子网掩码存入tempMask结构体中
														}
												 }
									   }
									   else goto UDPInvalid;
						  break;

						  case DHCP_ROUTER:
						                s++;
										j= SHCPMes.options[s++];
										if(j>=4u)  //大小为4的整数倍
										{
										         if(!DHCPState.bits.bOfferReceived)	 // Check to see if this is the first offer
												 {
												         for(i=0;i<4;i++)
														 {
														     tempGateway[i]=DHCPMes.options[s++]; //将网关存入tempGateway结构体中
														 }
												 }
										}
										else 
										  goto UDPInvalid;
										j-=4;
										while(j--) 
										s++;	//放弃其他 Router地址,指针加1
						  break;
						  
						  case DHCP_SERVER_IDENTIFIER:
						                s++;
										if(DHCPMes.options[s++]==4u)
										{
										          for(i=0;i<4;i++)
												  {
												         tempServerID[i]=DHCPMes.options[s++]; //将服务器地址存放在tempServerID结构体中
												  }
										}
										else goto UDPInvalid;
						  break;

						  case DHCP_END_OPTION:
										lbDone=TRUE;										 
						  break;

						  default:	   // Ignore all unsupport tags.	        
								s++;
								j=DHCPMes.options[s++];	  //unsupport size
								while(j--)  s++;   		  //Ignore all unsupport data

			}while( !lbDone );	 //end of do
		   	     

	  }//end of if(DHCPMes.op=BOOT_REPLY)

	  if(type==DHCP_OFFER_MESSAGE)
	  {
	      	   DHCPServerID.Val=tempServerID.Val;
			   DHCPState.bits.bOfferReceived=TRUE;
	  }
 	  else
	  {
	     if(DHCPServerID.Val!=tempServerID.Val) //make sure that received server id matches with our previous one.
          {
		     type = DHCP_UNKNOWN_MESSAGE ;
		  }
	  }	

	  /*    
		处理完毕   待写。。。UDPDiscard();
	  */
	  return type;

   UDPInvalid:
	   /*    
		处理完毕	待写。。。。。	UDPDiscard();
	  */
	  return DHCP_UNKNOWN_MESSAGE;

 } //end of DHCP_Receive




****************************************************************************************************************8

dhcp头文件

typedef unsigned short int WORD;            // 16-bit(全局)
typedef unsigned long LONG;                // 32-bit(全局)

typedef enum _SM_DHCP
{
//	SM_DHCP_INIT_FIRST_TIME,
    SM_DHCP_INIT,
//    SM_DHCP_RESET_WAIT,
    SM_DHCP_BROADCAST,
    SM_DHCP_DISCOVER,
    SM_DHCP_REQUEST,
    SM_DHCP_BIND,
    SM_DHCP_BOUND,
    SM_DHCP_DISABLED,
} SM_DHCP;


typedef union DHCP_STATE
{
    struct
    {
        unsigned char bIsBound : 1;
        unsigned char bOfferReceived : 1;
    } bits;
    INT8U Val;
} DHCP_STATE;

typedef struct _APP_CONFIG
{
    IP_ADDR     MyIPAddr;
    MAC_ADDR    MyMACAddr;
    IP_ADDR     MyMask;
    IP_ADDR     MyGateway;
} APP_CONFIG;

typedef struct _MAC_ADDR
{
    INT8U v[6];
} MAC_ADDR;

typedef union _IP_ADDR
{
    INT8U        v[4];
    LONG       Val;
} IP_ADDR;

typedef struct _DHCP_MES
{
    INT8U		op   ;
	INT8U		htype ;
	INT8U		hlen   ;
	INT8U 		hops   ;
	INT8U		xid [4];
	INT8U		secs [2];
	INT8U		flags [2];
	INT8U		ciaddr [4];
	INT8U		yiaddr [4];
	INT8U		siaddr [4];
	INT8U		giaddr [4];
	INT8U		chaddr [16];
	INT8U		sname [64];
	INT8U		file [128];
	INT8U       options[312];    //长度不定
}  DHCP_MES;

typedef INT8U UDP_SOCKET;







#define DHCPDisable()       (smDHCPState = SM_DHCP_DISABLED)
#define DHCPIsBound()       (DHCPState.bits.bIsBound)

#if !defined(THIS_IS_DHCP)
    extern DHCP_STATE DHCPState;
#endif

#if !defined(THIS_IS_DHCP)
    extern SM_DHCP smDHCPState;
#endif


void DHCPTask(void);
void DHCPReset(void);

 

抱歉!评论已关闭.