@ -68,62 +68,83 @@ void DHCPServerApp_Callback(void)
DHCP_Header_t * const AppData = ( DHCP_Header_t * ) uip_appdata ;
DHCP_Header_t * const AppData = ( DHCP_Header_t * ) uip_appdata ;
uint16_t AppDataSize = 0 ;
uint16_t AppDataSize = 0 ;
uint8_t DHCPMessageType ;
/* Only process when new data arrives - don't retransmit lost packets */
if ( ! ( DHCPCommon_GetOption ( AppData - > Options , DHCP_OPTION_MSG_TYPE , & DHCPMessageType ) ) )
if ( uip_newdata ( ) )
return ;
uip_ipaddr_t Netmask , GatewayIPAddress ;
struct uip_eth_addr RemoteMACAddress ;
uint32_t TransactionID ;
memcpy ( & RemoteMACAddress , & AppData - > ClientHardwareAddress , sizeof ( struct uip_eth_addr ) ) ;
uip_getnetmask ( & Netmask ) ;
uip_getdraddr ( & GatewayIPAddress ) ;
TransactionID = AppData - > TransactionID ;
switch ( DHCPMessageType )
{
{
case DHCP_DISCOVER :
/* Get the DHCP message type (if present), otherwise early-abort */
AppDataSize + = DHCPServerApp_FillDHCPHeader ( AppData , DHCP_OFFER , & RemoteMACAddress , TransactionID ) ;
uint8_t DHCPMessageType ;
if ( ! ( DHCPCommon_GetOption ( AppData - > Options , DHCP_OPTION_MSG_TYPE , & DHCPMessageType ) ) )
AppDataSize + = DHCPCommon_SetOption ( AppData - > Options , DHCP_OPTION_SUBNET_MASK ,
return ;
sizeof ( uip_ipaddr_t ) , & Netmask ) ;
AppDataSize + = DHCPCommon_SetOption ( AppData - > Options , DHCP_OPTION_ROUTER ,
uip_ipaddr_t Netmask , GatewayIPAddress , PreferredClientIP ;
sizeof ( uip_ipaddr_t ) , & GatewayIPAddress ) ;
struct uip_eth_addr RemoteMACAddress ;
uint32_t TransactionID ;
/* Send the DHCP OFFER packet */
uip_poll_conn ( BroadcastConnection ) ;
/* Get configured network mask, gateway IP and extract out DHCP transaction ID and remote IP */
memcpy ( & uip_udp_conn - > ripaddr , & uip_broadcast_addr , sizeof ( uip_ipaddr_t ) ) ;
uip_getnetmask ( & Netmask ) ;
uip_udp_send ( AppDataSize ) ;
uip_getdraddr ( & GatewayIPAddress ) ;
memcpy ( & RemoteMACAddress , & AppData - > ClientHardwareAddress , sizeof ( struct uip_eth_addr ) ) ;
break ;
TransactionID = AppData - > TransactionID ;
case DHCP_REQUEST :
if ( ! ( DHCPServerApp_CheckIfIPLeased ( & AppData - > YourIP ) ) )
/* Try to extract out the client's preferred IP address if it is indicated in the packet */
{
if ( ! ( DHCPCommon_GetOption ( AppData - > Options , DHCP_OPTION_REQ_IPADDR , & PreferredClientIP ) ) )
AppDataSize + = DHCPServerApp_FillDHCPHeader ( AppData , DHCP_ACK , & RemoteMACAddress , TransactionID ) ;
memcpy ( & PreferredClientIP , & uip_all_zeroes_addr , sizeof ( uip_ipaddr_t ) ) ;
switch ( DHCPMessageType )
{
case DHCP_DISCOVER :
/* If no preference was made or the preferred IP is already taken, find a new address */
if ( DHCPServerApp_CheckIfIPLeased ( & PreferredClientIP ) )
DHCPServerApp_GetUnleasedIP ( & PreferredClientIP ) ;
/* Create a new DHCP OFFER packet with the offered IP address */
AppDataSize + = DHCPServerApp_FillDHCPHeader ( AppData , DHCP_OFFER , & RemoteMACAddress , & PreferredClientIP , TransactionID ) ;
/* Add network mask and router information to the list of DHCP OFFER packet options */
AppDataSize + = DHCPCommon_SetOption ( AppData - > Options , DHCP_OPTION_SUBNET_MASK ,
AppDataSize + = DHCPCommon_SetOption ( AppData - > Options , DHCP_OPTION_SUBNET_MASK ,
sizeof ( uip_ipaddr_t ) , & Netmask ) ;
sizeof ( uip_ipaddr_t ) , & Netmask ) ;
AppDataSize + = DHCPCommon_SetOption ( AppData - > Options , DHCP_OPTION_ROUTER ,
AppDataSize + = DHCPCommon_SetOption ( AppData - > Options , DHCP_OPTION_ROUTER ,
sizeof ( uip_ipaddr_t ) , & GatewayIPAddress ) ;
sizeof ( uip_ipaddr_t ) , & GatewayIPAddress ) ;
DHCPServerApp_LeaseIP ( & AppData - > YourIP ) ;
/* Send the DHCP OFFER packet */
}
uip_poll_conn ( BroadcastConnection ) ;
else
memcpy ( & uip_udp_conn - > ripaddr , & uip_broadcast_addr , sizeof ( uip_ipaddr_t ) ) ;
{
uip_udp_send ( AppDataSize ) ;
AppDataSize + = DHCPServerApp_FillDHCPHeader ( AppData , DHCP_NAK , & RemoteMACAddress , TransactionID ) ;
}
break ;
case DHCP_REQUEST :
/* Send the DHCP ACK or NAK packet */
/* Check to see if the requested IP address has already been leased to a client */
uip_poll_conn ( BroadcastConnection ) ;
if ( ! ( DHCPServerApp_CheckIfIPLeased ( & PreferredClientIP ) ) )
memcpy ( & uip_udp_conn - > ripaddr , & uip_broadcast_addr , sizeof ( uip_ipaddr_t ) ) ;
{
uip_udp_send ( AppDataSize ) ;
/* Create a new DHCP ACK packet to accept the IP address lease */
AppDataSize + = DHCPServerApp_FillDHCPHeader ( AppData , DHCP_ACK , & RemoteMACAddress , & PreferredClientIP , TransactionID ) ;
break ;
case DHCP_RELEASE :
/* Add network mask and router information to the list of DHCP ACK packet options */
/* Mark the IP address as released in the allocation table */
AppDataSize + = DHCPCommon_SetOption ( AppData - > Options , DHCP_OPTION_SUBNET_MASK ,
DHCPServerApp_UnleaseIP ( & uip_udp_conn - > ripaddr ) ;
sizeof ( uip_ipaddr_t ) , & Netmask ) ;
break ;
AppDataSize + = DHCPCommon_SetOption ( AppData - > Options , DHCP_OPTION_ROUTER ,
sizeof ( uip_ipaddr_t ) , & GatewayIPAddress ) ;
/* Mark the requested IP as leased to a client */
DHCPServerApp_LeaseIP ( & PreferredClientIP ) ;
}
else
{
/* Create a new DHCP NAK packet to reject the requested allocation */
AppDataSize + = DHCPServerApp_FillDHCPHeader ( AppData , DHCP_NAK , & RemoteMACAddress , & uip_all_zeroes_addr , TransactionID ) ;
}
/* Send the DHCP ACK or NAK packet */
uip_poll_conn ( BroadcastConnection ) ;
memcpy ( & uip_udp_conn - > ripaddr , & uip_broadcast_addr , sizeof ( uip_ipaddr_t ) ) ;
uip_udp_send ( AppDataSize ) ;
break ;
case DHCP_RELEASE :
/* Mark the IP address as released in the allocation table */
DHCPServerApp_UnleaseIP ( & uip_udp_conn - > ripaddr ) ;
break ;
}
}
}
}
}
@ -139,8 +160,9 @@ void DHCPServerApp_Callback(void)
*/
*/
static uint16_t DHCPServerApp_FillDHCPHeader ( DHCP_Header_t * const DHCPHeader ,
static uint16_t DHCPServerApp_FillDHCPHeader ( DHCP_Header_t * const DHCPHeader ,
const uint8_t DHCPMessageType ,
const uint8_t DHCPMessageType ,
struct uip_eth_addr * ClientHardwareAddress ,
const struct uip_eth_addr * const ClientHardwareAddress ,
uint32_t TransactionID )
const uip_ipaddr_t * const PreferredClientIP ,
const uint32_t TransactionID )
{
{
/* Erase existing packet data so that we start will all 0x00 DHCP header data */
/* Erase existing packet data so that we start will all 0x00 DHCP header data */
memset ( DHCPHeader , 0 , sizeof ( DHCP_Header_t ) ) ;
memset ( DHCPHeader , 0 , sizeof ( DHCP_Header_t ) ) ;
@ -153,8 +175,7 @@ static uint16_t DHCPServerApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader,
DHCPHeader - > ElapsedSeconds = 0 ;
DHCPHeader - > ElapsedSeconds = 0 ;
DHCPHeader - > Flags = 0 ;
DHCPHeader - > Flags = 0 ;
memcpy ( & DHCPHeader - > NextServerIP , & uip_hostaddr , sizeof ( uip_ipaddr_t ) ) ;
memcpy ( & DHCPHeader - > NextServerIP , & uip_hostaddr , sizeof ( uip_ipaddr_t ) ) ;
if ( uip_ipaddr_cmp ( & DHCPHeader - > YourIP , & uip_all_zeroes_addr ) )
memcpy ( & DHCPHeader - > YourIP , PreferredClientIP , sizeof ( uip_ipaddr_t ) ) ;
DHCPServerApp_GetUnleasedIP ( & DHCPHeader - > YourIP ) ;
memcpy ( & DHCPHeader - > ClientHardwareAddress , ClientHardwareAddress , sizeof ( struct uip_eth_addr ) ) ;
memcpy ( & DHCPHeader - > ClientHardwareAddress , ClientHardwareAddress , sizeof ( struct uip_eth_addr ) ) ;
DHCPHeader - > Cookie = DHCP_MAGIC_COOKIE ;
DHCPHeader - > Cookie = DHCP_MAGIC_COOKIE ;
@ -176,12 +197,13 @@ static uint16_t DHCPServerApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader,
*
*
* \ return Boolean true if the IP has already been leased to a client , false otherwise .
* \ return Boolean true if the IP has already been leased to a client , false otherwise .
*/
*/
static bool DHCPServerApp_CheckIfIPLeased ( uip_ipaddr_t * IPAddress )
static bool DHCPServerApp_CheckIfIPLeased ( const uip_ipaddr_t * const IPAddress )
{
{
uint8_t Byte = ( IPAddress - > u8 [ 3 ] / 8 ) ;
uint8_t Byte = ( IPAddress - > u8 [ 3 ] / 8 ) ;
uint8_t Mask = ( 1 < < ( IPAddress - > u8 [ 3 ] % 8 ) ) ;
uint8_t Mask = ( 1 < < ( IPAddress - > u8 [ 3 ] % 8 ) ) ;
if ( ! ( IPAddress - > u8 [ 3 ] = = uip_hostaddr . u8 [ 3 ] ) & & ! ( LeasedIPs [ Byte ] & Mask ) )
/* Make sure that the requested IP address isn't already leased to the virtual server or another client */
if ( IPAddress - > u8 [ 3 ] & & ! ( IPAddress - > u8 [ 3 ] = = uip_hostaddr . u8 [ 3 ] ) & & ! ( LeasedIPs [ Byte ] & Mask ) )
return false ;
return false ;
else
else
return true ;
return true ;
@ -191,14 +213,17 @@ static bool DHCPServerApp_CheckIfIPLeased(uip_ipaddr_t* IPAddress)
*
*
* \ param [ out ] NewIPAddress Location where the generated IP Address should be stored
* \ param [ out ] NewIPAddress Location where the generated IP Address should be stored
*/
*/
static void DHCPServerApp_GetUnleasedIP ( uip_ipaddr_t * NewIPAddress )
static void DHCPServerApp_GetUnleasedIP ( uip_ipaddr_t * const NewIPAddress )
{
{
uip_ipaddr_copy ( NewIPAddress , & uip_hostaddr ) ;
uip_ipaddr_copy ( NewIPAddress , & uip_hostaddr ) ;
/** Look through the current subnet, skipping the broadcast and zero IP addresses */
for ( uint8_t IP = 1 ; IP < 254 ; IP + + )
for ( uint8_t IP = 1 ; IP < 254 ; IP + + )
{
{
/* Update new IP address to lease with the current IP address to test */
NewIPAddress - > u8 [ 3 ] = IP ;
NewIPAddress - > u8 [ 3 ] = IP ;
/* If we've found an unleased IP, abort with the updated IP stored for the called */
if ( ! ( DHCPServerApp_CheckIfIPLeased ( NewIPAddress ) ) )
if ( ! ( DHCPServerApp_CheckIfIPLeased ( NewIPAddress ) ) )
return ;
return ;
}
}
@ -211,11 +236,12 @@ static void DHCPServerApp_GetUnleasedIP(uip_ipaddr_t* NewIPAddress)
*
*
* \ pre The IP address must be within the same / 24 subnet as the virtual webserver .
* \ pre The IP address must be within the same / 24 subnet as the virtual webserver .
*/
*/
static void DHCPServerApp_LeaseIP ( uip_ipaddr_t * IPAddress )
static void DHCPServerApp_LeaseIP ( const uip_ipaddr_t * const IPAddress )
{
{
uint8_t Byte = ( IPAddress - > u8 [ 3 ] / 8 ) ;
uint8_t Byte = ( IPAddress - > u8 [ 3 ] / 8 ) ;
uint8_t Mask = ( 1 < < ( IPAddress - > u8 [ 3 ] % 8 ) ) ;
uint8_t Mask = ( 1 < < ( IPAddress - > u8 [ 3 ] % 8 ) ) ;
/* Mark the IP address as leased in the allocation table */
LeasedIPs [ Byte ] | = Mask ;
LeasedIPs [ Byte ] | = Mask ;
}
}
@ -226,11 +252,12 @@ static void DHCPServerApp_LeaseIP(uip_ipaddr_t* IPAddress)
*
*
* \ pre The IP address must be within the same / 24 subnet as the virtual webserver .
* \ pre The IP address must be within the same / 24 subnet as the virtual webserver .
*/
*/
static void DHCPServerApp_UnleaseIP ( uip_ipaddr_t * IPAddress )
static void DHCPServerApp_UnleaseIP ( const uip_ipaddr_t * const IPAddress )
{
{
uint8_t Byte = ( IPAddress - > u8 [ 3 ] / 8 ) ;
uint8_t Byte = ( IPAddress - > u8 [ 3 ] / 8 ) ;
uint8_t Mask = ( 1 < < ( IPAddress - > u8 [ 3 ] % 8 ) ) ;
uint8_t Mask = ( 1 < < ( IPAddress - > u8 [ 3 ] % 8 ) ) ;
/* Mark the IP address as unleased in the allocation table */
LeasedIPs [ Byte ] & = ~ Mask ;
LeasedIPs [ Byte ] & = ~ Mask ;
}
}
# endif
# endif