📄 dhcp.c
字号:
then copy it to the buffer chain. Allocate the contiguous memory here. */
status = NU_Allocate_Memory( &System_Memory, (VOID **)&pkt,
sizeof(DHCPLAYER), NU_NO_SUSPEND);
if (status != NU_SUCCESS)
return (status);
memset(pkt, 0, sizeof(DHCPLAYER) );
pkt->dp_op = BOOTREQUEST; /* opcode, 1 octet */
pkt->dp_htype = HARDWARE_TYPE; /* hardware type, 1 octet */
pkt->dp_hlen = DADDLEN; /* hardware address length, 1 octet */
pkt->dp_xid = ds_ptr->dhcp_xid;
pkt->dp_secs = 0;
if (device->dev_addr.dev_dhcp_state == DHCP_RENEW_STATE)
pkt->dp_flags= 0;
else
pkt->dp_flags= INTSWAP(DHCP_BROADCAST_FLAG); /* set broadcast flag. */
/* Fill in the client's hardware address. */
memcpy(pkt->dp_chaddr, ds_ptr->dhcp_mac_addr, DADDLEN);
len = sizeof(pkt->dp_op) +
sizeof(pkt->dp_htype) +
sizeof(pkt->dp_hlen) +
sizeof(pkt->dp_hops) +
sizeof(pkt->dp_xid) +
sizeof(pkt->dp_secs) +
sizeof(pkt->dp_flags) +
sizeof(pkt->dp_ciaddr) +
sizeof(pkt->dp_yiaddr) +
sizeof(pkt->dp_siaddr) +
sizeof(pkt->dp_giaddr) +
sizeof(pkt->dp_chaddr) +
sizeof(pkt->dp_sname) +
sizeof(pkt->dp_file);
pt = pkt->dp_vend;
PUT32(pt, 0, DHCP_COOKIE);
pt += 4;
*pt++ = DHCP_MSG_TYPE;
*pt++ = 1;
*pt++ = msg_type;
*pt++ = DHCP_CLIENT_CLASS_ID;
*pt++ = 7;
*pt++ = HARDWARE_TYPE;
*pt++ = ds_ptr->dhcp_mac_addr[0];
*pt++ = ds_ptr->dhcp_mac_addr[1];
*pt++ = ds_ptr->dhcp_mac_addr[2];
*pt++ = ds_ptr->dhcp_mac_addr[3];
*pt++ = ds_ptr->dhcp_mac_addr[4];
*pt++ = ds_ptr->dhcp_mac_addr[5];
len += 16;
if (msg_type == DHCPDISCOVER) /* Building a Discover packet. */
{
/* Currently there are no special options that need to be added to a
discover. */
}
else if (msg_type == DHCPRELEASE) /* Building a release packet. */
{
/* Fill in ciaddr. */
PUT32(pkt->dp_ciaddr.is_ip_addrs, 0, device->dev_addr.dev_ip_addr);
}
else /* Must be building a request packet. */
{
/* Only fill in ciaddr if in the renewing or rebinding state. */
if ( (device->dev_addr.dev_dhcp_state == DHCP_RENEW_STATE) ||
(device->dev_addr.dev_dhcp_state == DHCP_REBIND_STATE) )
PUT32(pkt->dp_ciaddr.is_ip_addrs, 0, device->dev_addr.dev_ip_addr);
/* Only send the DHCP_Requested IP address during the INIT state. */
if (device->dev_addr.dev_dhcp_state == DHCP_REQUESTING_STATE)
{
*pt++ = DHCP_REQUEST_IP;
*pt++ = 4;
*pt++ = ds_ptr->dhcp_yiaddr[0];
*pt++ = ds_ptr->dhcp_yiaddr[1];
*pt++ = ds_ptr->dhcp_yiaddr[2];
*pt++ = ds_ptr->dhcp_yiaddr[3];
len += 6;
}
/* Only send the server ID option if in the INIT state. */
if (device->dev_addr.dev_dhcp_state == DHCP_REQUESTING_STATE)
{
/* tell all servers that responded to the DHCPDISCOVER broadcast */
/* that the following server has been selected. */
*pt++ = DHCP_SERVER_ID;
*pt++ = 4;
*pt++ = ds_ptr->dhcp_siaddr[0];
*pt++ = ds_ptr->dhcp_siaddr[1];
*pt++ = ds_ptr->dhcp_siaddr[2];
*pt++ = ds_ptr->dhcp_siaddr[3];
len += 6;
}
if( ds_ptr->dhcp_opts )
{
/* The user wishes to make some specific requests as to which
options the server should return. */
/* Copy the application specified options. */
memcpy(pt, ds_ptr->dhcp_opts, ds_ptr->dhcp_opts_len);
pt += ds_ptr->dhcp_opts_len;
len += ds_ptr->dhcp_opts_len;
}
}
/* Mark the end of the options list. */
*pt = DHCP_END;
len++;
/* Some DHCP servers (SUN Solaris) reject DHCP messages that are less than
300 bytes in length. Pad the message if necessary. */
if (len < 300)
len = 300;
status = DHCP_Pkt_Copy((UINT8 *)pkt, buf_ptr, len);
NU_Deallocate_Memory(pkt);
if (status != NU_SUCCESS)
return (NU_DHCP_INIT_FAILED);
else
return (NU_SUCCESS);
} /* DHCP_Init_DHCP_Layer */
/****************************************************************************
* FUNCTION
*
* DHCP_Pkt_Copy
*
* DESCRIPTION
*
* Copy a DHCP message into a Nucleus NET buffer chain.
*
* INPUTS
*
* buffer
* buf_ptr
* length
*
* OUTPUTS
*
* NU_SUCCESS Success.
* -1 Failure.
*
******************************************************************************/
static STATUS DHCP_Pkt_Copy(UINT8 *buffer, NET_BUFFER *buf_ptr, INT length)
{
INT current_size, total_size = length;
NET_BUFFER *next_buf;
/* Point to where the DHCP packet should begin. */
buf_ptr->data_ptr = buf_ptr->mem_parent_packet + NET_MAX_UDP_HEADER_SIZE;
/* Chain the DHCP Request Packet */
if (total_size > NET_PARENT_BUFFER_SIZE)
{
current_size = NET_PARENT_BUFFER_SIZE - NET_MAX_UDP_HEADER_SIZE;
total_size = total_size - current_size;
}
else
{
current_size = total_size;
total_size = 0;
}
/* Copy DHCP Packet into first Buffer */
memcpy(buf_ptr->data_ptr, buffer, (unsigned int)current_size);
buf_ptr->data_len = current_size;
buf_ptr->mem_total_data_len = length;
/* Point to fresh data. */
buffer += current_size;
/* Point to the next buffer is there is one. */
next_buf = buf_ptr->next_buffer;
/* Check to make sure there is data to store in the mem_packet */
while (total_size && next_buf)
{
/* Determine how much data can be copied to the next buffer. */
if (total_size > NET_MAX_BUFFER_SIZE)
current_size = NET_MAX_BUFFER_SIZE;
else
current_size = total_size;
total_size -= current_size;
/* Copy the remaining data in the chaining packets */
memcpy(next_buf->mem_packet, buffer, (unsigned int)current_size);
/* Set the Data pointer to the remainder of the packets. */
next_buf->data_ptr = next_buf->mem_packet;
next_buf->next = NU_NULL;
next_buf->data_len = current_size;
/* Point to the next buffer is there is one. */
buffer = buffer + current_size;
/* Point to the next buffer in the chain. */
next_buf = next_buf->next_buffer;
}
/* When the original buffer chain was aloocated it was done so assuming
that a max DHCP message would be built. However, this is unlikely.
If there are any unused buffers in the chain then free them. The main
reason for doing this is incase the driver is not designed to handle a
buffer chain that contains empty buffers. */
for (next_buf = buf_ptr; next_buf; next_buf = next_buf->next_buffer)
{
/* If there is a buffer after the current one and that buffer contains
no data then free that buffer and any that follow it. */
if (next_buf->next_buffer && (next_buf->next_buffer->data_len == 0))
{
MEM_One_Buffer_Chain_Free (next_buf->next_buffer,
&MEM_Buffer_Freelist);
next_buf->next_buffer = NU_NULL;
}
}
/* At this point total_size should be 0. If it is not 0 then something
has gone wrong. */
if(total_size)
return NU_DHCP_INIT_FAILED;
else
return NU_SUCCESS;
} /* DHCP_Pkt_Copy */
/******************************************************************************
* FUNCTION
*
* DHCP_Send
*
* DESCRIPTION
*
* Send a DHCP Message.
*
* INPUTS
*
* buf_ptr
* int_face
* dest_ip
*
* OUTPUTS
*
* NU_SUCCESS
* -1 Fail.
*
******************************************************************************/
static STATUS DHCP_Send( DV_DEVICE_ENTRY *device, DHCP_STRUCT *ds_ptr, UINT8 msg_type)
{
STATUS status;
INT32 flags;
SCK_SOCKADDR_IP sa;
NET_BUFFER *buf_ptr;
IPLAYER HUGE *ip_ptr;
/* build the first DHCP discovery message */
if ((status = DHCP_Build_Message(&buf_ptr, ds_ptr, device, msg_type)) != NU_SUCCESS)
return status;
ip_ptr = (IPLAYER *)(buf_ptr->data_ptr);
/* Set up MAC layer */
sa.sck_family = SK_FAM_IP;
sa.sck_len = sizeof (sa);
sa.sck_addr = GET32(ip_ptr, IP_DEST_OFFSET);
/* Grab the semaphore because we are about to change the interface
that the DHCP request will be sent over. */
NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
/* The device will not send packets until an IP address is attached.
Temporarily trick it into thinking an IP address is attached so this
request can be sent. Then set it back. */
flags = device->dev_flags;
device->dev_flags |= (DV_UP | DV_RUNNING);
/* Send the packet. */
status = (*(device->dev_output)) ( buf_ptr, device, &sa, NU_NULL );
device->dev_flags = flags;
NU_Release_Semaphore(&TCP_Resource);
return status;
} /* DHCP_Send */
/****************************************************************************
* FUNCTION
*
* DHCP_Init_UDP_Layer
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -