📄 dhcp.c
字号:
/* Set the DHCP state. */
device->dev_addr.dev_dhcp_state = DHCP_REQUESTING_STATE;
if( (found & ACCEPT_BIT) == ACCEPT_BIT )
{
retval = DHCP_Send_Request(ds_ptr, socketd, device);
if( retval == NU_SUCCESS)
{
if ( DEV_Attach_IP_To_Device( dv_name, ds_ptr->dhcp_yiaddr,
ds_ptr->dhcp_net_mask) != NU_SUCCESS)
{
NERRS_Log_Error( NERR_FATAL, __FILE__, __LINE__);
retval = NU_DHCP_INIT_FAILED;
} /* if status */
else
{
/* Set the DHCP state. */
device->dev_addr.dev_dhcp_state = DHCP_BOUND_STATE;
/* Set up the timer events that will renew the lease. */
DHCP_Init_Timers(device);
}
} /* If found */
} /* Accept Bit */
else
{
NERRS_Log_Error( NERR_FATAL, __FILE__, __LINE__);
retval = NU_DHCP_REQUEST_FAILED;
}
DHCP_Exit:
if (socketd >= 0)
NU_Close_Socket(socketd);
NU_USER_MODE();
return(retval);
} /* NU_Dhcp */
/******************************************************************************
* FUNCTION
*
* DHCP_Send_Request
*
* DESCRIPTION
*
* Send a DHCP Request message.
*
* INPUTS
*
* ds_ptr Pointer to DHCP structure.
* socketd Socket descriptor.
* device Pointer to device structure.
*
* OUTPUTS
*
* NU_SUCCESS
* NU_NO_BUFFERS
* NU_DHCP_INIT_FAILED
* NU_DHCP_REQUEST_FAILED
*
******************************************************************************/
static STATUS DHCP_Send_Request( DHCP_STRUCT *ds_ptr, INT socketd,
DV_DEVICE_ENTRY *device)
{
INT i;
INT32 delay, rand;
INT found;
STATUS status;
found = 0;
/* The (i + 2) check is because the third element of the
TCP backoff array is used first and we don't want to
extend past the end of the backoff array. See it's use below. */
for( i = 0; (i < RETRIES_COUNT) && ( (i + 2) < TCP_MAX_BACKOFFS); i++ )
{
/* Send the packet. */
status = DHCP_Send(device, ds_ptr, DHCPREQUEST);
if( status != NU_SUCCESS )
{
NERRS_Log_Error( NERR_FATAL, __FILE__, __LINE__);
break;
}
/* Compute a delay between retransmissions of DHCP messages. RFC 2131
specifies that a randomized exponential backoff algorithm must be
used. The first retransmission should be at 4 seconds, then 8, then
16, etc., up to a max of 64. This value should be randomized by plus
or minus a second. */
/* Get a random number. */
rand = UTL_Rand();
/* Compute a number that is between 0 and SCK_Ticks_Per_Second. */
delay = rand % SCK_Ticks_Per_Second;
/* At this point we have a delay that is equal to some value between
0 and 1 second. Now an arbitrary bit has been chosen from the random
number. If this bit is set then change the sign of the delay. About
half the time we should end up with a negative number. */
if (rand & 0x80)
delay = (-delay);
/* Here we make use of the TCP backoff array. This array looks like
{1, 2, 4, 8, 16, .... 64, 64,..}. The first value taken from this
array will be 4 (i+2). 4 will be multiplied by SCK_Ticks_Per_Second and
the original delay will be added to it. The original delay
will be a number of ticks that is in the range of -1 to +1 seconds.
The final delay computed will be between 3 and 5 seconds (4 +|- 1). */
delay = (TCP_Backoff[i+2] * SCK_Ticks_Per_Second) + delay;
found = DHCP_Process_ACK( socketd, ds_ptr, device, (UINT32)delay);
if( found != 0 )
{
break;
}
found = 0;
}
if (found == 1)
return NU_SUCCESS;
else
return NU_DHCP_REQUEST_FAILED;
} /* DHCP_Send_Request */
/**************************************************************************
* FUNCTION
*
* NU_Dhcp_Release
*
* DESCRIPTION
*
* This function releases the address acquired by the NU_Dhcp
* function call.
*
* INPUTS
*
* ds_ptr Pointer to DHCP Structure that
* contains data that can be obtained
* at the application layer.
* dv_name Pointer to Devices name.
*
* OUTPUTS
*
* NU_SUCCESS
* NU_DHCP_INIT_FAILED
* NU_NO_BUFFERS
*
**************************************************************************/
STATUS NU_Dhcp_Release( DHCP_STRUCT *ds_ptr, CHAR *dv_name)
{
DV_DEVICE_ENTRY *device;
STATUS status;
NU_SUPERV_USER_VARIABLES
if ((ds_ptr == NU_NULL) || (dv_name == NU_NULL))
return (NU_INVALID_PARM);
/* Switch to supervisor mode. */
NU_SUPERVISOR_MODE();
/* get a pointer to the interface structure. */
device = DEV_Get_Dev_By_Name(dv_name);
/* Was a valid device found? */
if (!device || (device->dev_mtu < DHCP_MAX_HEADER_SIZE))
{
NU_USER_MODE();
return (NU_DHCP_INIT_FAILED);
}
/* Go ahead and clear the IP address renewal and rebinding events. */
UTL_Timerunset (DHCP_RENEW, (UINT32)device, (INT32)1);
UTL_Timerunset (DHCP_REBIND, (UINT32)device, (INT32)1);
/* Send the release message. */
status = DHCP_Send(device, ds_ptr, DHCPRELEASE);
if( status != NU_SUCCESS )
{
NERRS_Log_Error( NERR_FATAL, __FILE__, __LINE__);
NU_USER_MODE();
return(-1);
}
DEV_Detach_IP_From_Device(dv_name);
NU_USER_MODE();
return(0);
} /* NU_Dhcp_Release */
/****************************************************************************
* FUNCTION
*
* DHCP_Process_Offer
*
* DESCRIPTION
*
* Process a DHCP offer message.
*
* INPUTS
*
* socketd Socket Descriptor to retrieve data from.
* ds_ptr Pointer to DHCP Structure that contains
* data that can be obtained at the
* application layer.
* device Pointer to the device.
* timeout Timeout value used for NU_Select.
*
* OUTPUTS
*
* NU_SUCCESS
* NU_NO_SOCK_MEMORY
*
******************************************************************************/
static STATUS DHCP_Process_Offer( INT socketd, DHCP_STRUCT *ds_ptr,
DV_DEVICE_ENTRY *device, UINT32 timeout)
{
INT32 ret;
INT16 flen;
INT16 found = 0;
UINT32 vend_cookie;
UINT8 *pt;
DHCPLAYER *dhcp_ptr; /* DHCP uses a Bootp type struct */
FD_SET readfs;
STATUS status;
struct addr_struct fromaddr;
status = NU_Allocate_Memory(&System_Memory, (VOID **)&dhcp_ptr, IOSIZE,
(UNSIGNED)NU_NO_SUSPEND);
if (status != NU_SUCCESS)
{
NERRS_Log_Error( NERR_FATAL, __FILE__, __LINE__);
return (NU_NO_SOCK_MEMORY);
}
do
{
NU_FD_Init(&readfs);
NU_FD_Set(socketd, &readfs);
/* Wait for a response to arrive. We are only interested in arriving
packets so the 3rd and 4th parameters are not needed. */
ret = NU_Select(NSOCKETS, &readfs, NU_NULL, NU_NULL, timeout);
if( ret == NU_NO_DATA )
break;
if(NU_FD_Check(socketd, &readfs) == NU_FALSE)
break;
fromaddr.family = NU_FAMILY_IP;
fromaddr.port = 0;
ret = NU_Recv_From(socketd, (CHAR *)dhcp_ptr, IOSIZE, 0, &fromaddr, &flen);
if( ret < 0 )
{
NERRS_Log_Error( NERR_FATAL, __FILE__, __LINE__);
break;
}
if( dhcp_ptr->dp_xid != ds_ptr->dhcp_xid )
continue;
/* At this point we are looking for a DHCP offer. If we did not get
one then move on to the next one. Add 4 to get past the cookie. */
if (DHCP_Message_Type(dhcp_ptr->dp_vend + 4) != DHCPOFFER)
continue;
/* Validate the DHCPOFFER. */
if(DHCP_Validate(ds_ptr, device->dev_net_if_name, dhcp_ptr) == 0 )
continue;
IP_ADDR_COPY(ds_ptr->dhcp_siaddr, dhcp_ptr->dp_siaddr.is_ip_addrs);
IP_ADDR_COPY(ds_ptr->dhcp_giaddr, dhcp_ptr->dp_giaddr.is_ip_addrs);
IP_ADDR_COPY(ds_ptr->dhcp_yiaddr, dhcp_ptr->dp_yiaddr.is_ip_addrs);
memcpy(ds_ptr->dhcp_sname, dhcp_ptr->dp_sname, sizeof(ds_ptr->dhcp_sname) );
memcpy(ds_ptr->dhcp_file, dhcp_ptr->dp_file, sizeof(ds_ptr->dhcp_file) );
vend_cookie = GET32(dhcp_ptr->dp_vend, 0);
/* test to see if cookie is a vendor cookie */
if( vend_cookie == DHCP_COOKIE )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -