DHCP客户端实现(初稿)
来源:互联网 发布:淘宝卖小孩衣服赚钱吗 编辑:程序博客网 时间:2024/04/28 06:09
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 sizewhile(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{ INT8Uop ;INT8Uhtype ;INT8Uhlen ;INT8U hops ;INT8Uxid [4];INT8Usecs [2];INT8Uflags [2];INT8Uciaddr [4];INT8Uyiaddr [4];INT8Usiaddr [4];INT8Ugiaddr [4];INT8Uchaddr [16];INT8Usname [64];INT8Ufile [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;#endifvoid DHCPTask(void);void DHCPReset(void);
- DHCP客户端实现(初稿)
- DHCP+服务器配置+客户端搭建+及实现
- 如何使用W7100A实现DHCP客户端?
- Linux下DHCP协议解析及客户端源码实现
- 网络教学资源平台设计与实现--用例图(初稿)
- DHCP客户端设置(solaris)
- 开题报告(初稿)
- 南山游记(初稿)
- 远程终端(初稿)
- 五子棋协议(初稿)
- 信号(初稿)
- 神经网络总结(初稿)
- 虚拟机安装(初稿)
- 访问 客户端 DHCP 进行传播
- 移植 DHCP 客户端 到ARM
- 站桩功(初稿)王芗斋 著
- 安全开发手册(初稿)
- 【java】大数类(初稿)
- 实时传输协议(RTP)和实时控制协议(RTCP)
- WIN32 递归方式删除文件和文件夹
- javascript 事件队列加载函数 addLoadEvent
- 包及访问控制权限
- s2sh中出现乱码
- DHCP客户端实现(初稿)
- [MSSQL]语句查询每个分组的前N条记录的实现方法
- 做设计的时间是不是短了呢?
- 《大话处理器》连载—PC机结构探秘(6)显示设备——脸面(1)
- 程序员从初级到中级10个秘诀
- 事情似乎才刚刚开始
- POJ 2823 Sliding Window 堆 / 单调队列
- mbuf
- win7 64位注册表操作兼容问题解决(vc6)