📄 dhcp.c
字号:
/******************************************************************
* dhcp.c: Dynamic Host Configuration Protocol
*
* Copyright (c) 2001 Atmel Corporation.
* All Rights Reserved.
*
* You are autorized to use, copy and distribute this software only at
* a single site (the term "site" meaning a single company location).
* This copyright notice must be included in any copy, modification
* or portion of this software merged into another program.
*
* This software is licenced solely for use with Atmel AVR micro
* controller family. The software may not be modified to execute on
* any other microcontroller architectures
*
* This software is provided "as is"; Without warranties either express
* or implied, including any warranty regarding merchantability,
* fitness for a particular purpose or noninfringement.
*
* In no event shall Atmel or its suppliers be liable for any special,
* indirect,incidential or concequential damages resulting from the
* use or inability to use this software.
*
* Revision history:
* January 17, 2001: Version 1.0 Created by JB
* July 13, 2001 Version 1.2 JB
* - Changed to IAR compiler V2.25
* - Renamed flash file functions to avoid conflict with
* standard file I/O names
* - Bug fixes in HTTP
* - Speed optimization in TCP
*
*******************************************************************/
#define ENABLE_BIT_DEFINITIONS
#include "dhcp.h"
#include "udp.h"
#include "ethernet.h"
#include "main.h"
#include "dataflash.h"
#include <iom103.h>
#include <ina90.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define SwapEndian(in) (in >> 24) | \
((in & 0x00FF0000) >> 8) |\
((in & 0x0000FF00) << 8) |\
(in << 24)
/*macros*/
#define TO_UINT(x) ((x) / 2)
#define TO_ULONG(x) ((x) / 4)
#define LO(x) ((unsigned char) ((x)&0x00ff)) //returns the lower end byte of an integer
#define HI(x) ((unsigned char) (((x)>>8)&0x00ff)) //returns the higher end byte of an integer
#define TOINT(x,y) (((x<<8)&0xff00) | (y&0x00ff) ) //combines two bytes into an integer
/*dhcp states*/
#define INITREBOOT 0
#define REBOOTING 1
#define INIT 2
#define SELECTING 3
#define REQUESTING 4
#define BOUND 5
#define RENEWING 6
#define REBINDING 7
/*when dhcpConf is set the IP-layer will forward all UDP datagrams and ignores the dest. IP-address field*/
extern unsigned char dhcpConf;
extern config_type ID;
unsigned char dhcpState = INITREBOOT; //initial state INITREBOOT
UDPB dhcpBuffer; //buffer for receiving/sending packets
struct { //varouis status varaiables required by dhcp
unsigned char XID0,XID1,XID2,XID3;
int ip0,ip1;
int sId0,sId1;
unsigned int nextEvent;
unsigned int cnt;
unsigned int min;
unsigned int arpWait;
unsigned char minEvent; //is set when min is incremented
}dhcpStatus;
// char msg[100]; //for debuging
void DHCP(void)
{
unsigned char retranMax; //max number of retransmitions, used in states REBOOTING and REQUESTING
unsigned char * pdata = &dhcpBuffer.data[DHCP_FIELD_OPTIONS+findOption(DHCP_OPTION_SERVERID)+2];
unsigned char msg_data = dhcpBuffer.data[DHCP_FIELD_OPTIONS+findOption(DHCP_OPTION_MSGTYPE)+2];
for (;;)
{
retranMax=DHCP_RETRAN;
switch (dhcpState)
{
case INITREBOOT:
dhcpConf=1; //set dhcp configuration flag, this will make the IP-layer
//forward all UDP datagrams and ignores the dest. IP-address field
dhcpStatus.ip0=EEgetInt(DHCP_EEADDRESS); //read the last obtained IP-address from EEPROM
dhcpStatus.ip1=EEgetInt(DHCP_EEADDRESS+2);
if ( dhcpStatus.ip0==0xffff && dhcpStatus.ip1==0xffff ) //check if there was an IP-address stored in EEPROM
{
dhcpState=INIT; //if no IP-address was found, go to state INIT
}
else
{
sendDHCPREQUEST();
dhcpState=REBOOTING;
}
break;
case REBOOTING:
if (wait((DHCP_RETRAN+1)-retranMax)) //wait longer for each retransmition, as defined in rfc2131
{
if (msg_data == DHCPACK) //if ack is received
{
/* read server identifier option */
dhcpStatus.sId0 = TOINT(pdata[2],pdata[3]);
dhcpStatus.sId1 = TOINT(pdata[4],pdata[5]);
/*configure the EWS with the obtained IP*/
ID.IP0 = TOINT(pdata[2],pdata[3]);
ID.IP1 = TOINT(pdata[4],pdata[5]);
dhcpMAC(dhcpStatus.sId0,dhcpStatus.sId1); //dhcpserver (ip,mac) is stored permanently in ARP-table
calcT1(); //calculate when to enter state RENEWING
dhcpStatus.min=0;
dhcpConf=0;
dhcpState=BOUND;
}
else if (msg_data == DHCPNAK)
{
dhcpState=INIT;
}
}
else if (retranMax == 0) //if maximum retransmitions is reached go to state INIT
{
dhcpState=INIT;
}
else
{
retranMax--;
sendDHCPREQUEST();
}
break;
case INIT:
dhcpConf=1; //set dhcp configuration flag, this will make the IP-layer
//forward all UDP datagrams and ignores the dest. IP-address field
ID.IP0=0; //clear the current IP-address
ID.IP1=0;
dhcpState=SELECTING;
break;
case SELECTING:
sendDHCPDISCOVER();
if (wait(2)) //wait for timeout or received UDP datagram on port 68
{
if (msg_data == DHCPOFFER)
{
if (checkXID()) //check if XID is correct
{
/* read server identifier option */
dhcpStatus.sId0 = TOINT(pdata[2],pdata[3]);
dhcpStatus.sId1 = TOINT(pdata[4],pdata[5]);
/* read offered ip adress from yiaddr */
dhcpStatus.ip0 = TOINT(dhcpBuffer.data[DHCP_FIELD_YIADDR],dhcpBuffer.data[DHCP_FIELD_YIADDR+1]);
dhcpStatus.ip1 = TOINT(dhcpBuffer.data[DHCP_FIELD_YIADDR+2],dhcpBuffer.data[DHCP_FIELD_YIADDR+3]);
sendDHCPREQUEST();
dhcpState=REQUESTING;
}
}
}
break;
case REQUESTING:
if (wait((DHCP_RETRAN+1)-retranMax)) //wait longer for each retranMaxsmition, as defined in rfc2131
{
if ( msg_data == DHCPACK && checkXID())
{
/*start using ip address assigned by dhcpserver*/
ID.IP0=TOINT(dhcpBuffer.data[DHCP_FIELD_YIADDR],dhcpBuffer.data[DHCP_FIELD_YIADDR+1]);
ID.IP1=TOINT(dhcpBuffer.data[DHCP_FIELD_YIADDR+2],dhcpBuffer.data[DHCP_FIELD_YIADDR+3]);
/*write leased ip address to EEPROM */
EEputInt(DHCP_EEADDRESS,ID.IP0);
EEputInt(DHCP_EEADDRESS+2,ID.IP1);
dhcpMAC(dhcpStatus.sId0,dhcpStatus.sId1); //dhcpserver (ip,mac) is stored permanently in ARP-table
calcT1(); //calculate when to enter state RENEWING
dhcpStatus.min=0;
dhcpConf=0; //dhcp configuration is done
dhcpState=BOUND;
}
else if ( msg_data == DHCPNAK)
{
dhcpState=INIT;
}
}
else if (retranMax ==0) //if all retransmissions fails, enter state INIT
{
dhcpState=INIT;
}
else
{
retranMax--;
sendDHCPREQUEST();
}
break;
case RENEWING:
if (dhcpStatus.minEvent) //only run if min has changed
{
sendDHCPREQUEST();
dhcpStatus.minEvent=0;
}
if (readUDP(68,&dhcpBuffer)) //if new data
{
if (msg_data == DHCPACK && checkXID())
{
calcT1();
dhcpStatus.min=0;
//dhcpConf=0;
dhcpState=BOUND;
}
else if (msg_data == DHCPNAK && checkXID())
{
dhcpState=INIT;
break;
}
}
if (dhcpStatus.min>=dhcpStatus.nextEvent) //T2 has occured enter state REBINING
{
dhcpStatus.nextEvent=(unsigned int) dhcpStatus.nextEvent*DHCP_TIMEOUT;
dhcpStatus.min=0;
dhcpState=REBINDING;
}
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -