📄 dhcp.c
字号:
}
/* did not get response to renew request? */
else if (dhcp->state == DHCP_RENEWING) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_timeout(): RENEWING, DHCP request timed out\n"));
/* just retry renewal */
/* note that the rebind timer will eventually time-out if renew does not work */
dhcp_renew(netif);
/* did not get response to rebind request? */
} else if (dhcp->state == DHCP_REBINDING) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_timeout(): REBINDING, DHCP request timed out\n"));
if (dhcp->tries <= 8) {
dhcp_rebind(netif);
} else {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_timeout(): RELEASING, DISCOVERING\n"));
dhcp_release(netif);
dhcp_discover(netif);
}
}
}
/**
* The renewal period has timed out.
*
* @param netif the netif under DHCP control
*/
static void dhcp_t1_timeout(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_t1_timeout()\n"));
if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
/* just retry to renew */
/* note that the rebind timer will eventually time-out if renew does not work */
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t1_timeout(): must renew\n"));
dhcp_renew(netif);
}
}
/**
* The rebind period has timed out.
*
*/
static void dhcp_t2_timeout(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t2_timeout()\n"));
if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
/* just retry to rebind */
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t2_timeout(): must rebind\n"));
dhcp_rebind(netif);
}
}
/**
*
* @param netif the netif under DHCP control
*/
static void dhcp_handle_ack(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
u8_t *option_ptr;
/* clear options we might not get from the ACK */
dhcp->offered_sn_mask.addr = 0;
dhcp->offered_gw_addr.addr = 0;
dhcp->offered_bc_addr.addr = 0;
/* lease time given? */
option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_LEASE_TIME);
if (option_ptr != NULL) {
/* remember offered lease time */
dhcp->offered_t0_lease = dhcp_get_option_long(option_ptr + 2);
}
/* renewal period given? */
option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T1);
if (option_ptr != NULL) {
/* remember given renewal period */
dhcp->offered_t1_renew = dhcp_get_option_long(option_ptr + 2);
} else {
/* calculate safe periods for renewal */
dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2;
}
/* renewal period given? */
option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T2);
if (option_ptr != NULL) {
/* remember given rebind period */
dhcp->offered_t2_rebind = dhcp_get_option_long(option_ptr + 2);
} else {
/* calculate safe periods for rebinding */
dhcp->offered_t2_rebind = dhcp->offered_t0_lease;
}
/* (y)our internet address */
ip_addr_set(&dhcp->offered_ip_addr, &dhcp->msg_in->yiaddr);
/**
* Patch #1308
* TODO: we must check if the file field is not overloaded by DHCP options!
*/
#if 0
/* boot server address */
ip_addr_set(&dhcp->offered_si_addr, &dhcp->msg_in->siaddr);
/* boot file name */
if (dhcp->msg_in->file[0]) {
dhcp->boot_file_name = mem_malloc(strlen(dhcp->msg_in->file) + 1);
strcpy(dhcp->boot_file_name, dhcp->msg_in->file);
}
#endif
/* subnet mask */
option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SUBNET_MASK);
/* subnet mask given? */
if (option_ptr != NULL) {
dhcp->offered_sn_mask.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
}
/* gateway router */
option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_ROUTER);
if (option_ptr != NULL) {
dhcp->offered_gw_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
}
/* broadcast address */
option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_BROADCAST);
if (option_ptr != NULL) {
dhcp->offered_bc_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
}
}
/**
* Start DHCP negotiation for a network interface.
*
* If no DHCP client instance was attached to this interface,
* a new client is created first. If a DHCP client instance
* was already present, it restarts negotiation.
*
* @param netif The lwIP network interface
* @return lwIP error code
* - ERR_OK - No error
* - ERR_MEM - Out of memory
*
*/
err_t dhcp_start(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
err_t result = ERR_OK;
LWIP_ASSERT("netif != NULL", netif != NULL);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_start(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num));
if (dhcp == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
dhcp = mem_malloc(sizeof(struct dhcp));
if (dhcp == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
netif->flags &= ~NETIF_FLAG_DHCP;
return ERR_MEM;
}
/* clear data structure */
memset(dhcp, 0, sizeof(struct dhcp));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): allocated dhcp"));
dhcp->pcb = udp_new();
if (dhcp->pcb == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not obtain pcb\n"));
mem_free((void *)dhcp);
dhcp = NULL;
netif->flags &= ~NETIF_FLAG_DHCP;
return ERR_MEM;
}
/* store this dhcp client in the netif */
netif->dhcp = dhcp;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): created new udp pcb\n"));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
} else {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE | 3, ("dhcp_start(): restarting DHCP configuration\n"));
}
/* (re)start the DHCP negotiation */
result = dhcp_discover(netif);
if (result != ERR_OK) {
/* free resources allocated above */
dhcp_stop(netif);
}
return result;
}
/**
* Inform a DHCP server of our manual configuration.
*
* This informs DHCP servers of our fixed IP address configuration
* by sending an INFORM message. It does not involve DHCP address
* configuration, it is just here to be nice to the network.
*
* @param netif The lwIP network interface
*
*/
void dhcp_inform(struct netif *netif)
{
struct dhcp *dhcp;
err_t result = ERR_OK;
dhcp = mem_malloc(sizeof(struct dhcp));
if (dhcp == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_inform(): could not allocate dhcp\n"));
return;
}
netif->dhcp = dhcp;
memset(dhcp, 0, sizeof(struct dhcp));
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_inform(): allocated dhcp\n"));
dhcp->pcb = udp_new();
if (dhcp->pcb == NULL) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_inform(): could not obtain pcb"));
mem_free((void *)dhcp);
return;
}
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_inform(): created new udp pcb\n"));
/* create and initialize the DHCP message header */
result = dhcp_create_request(netif);
if (result == ERR_OK) {
dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
dhcp_option_byte(dhcp, DHCP_INFORM);
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
/* TODO: use netif->mtu ?! */
dhcp_option_short(dhcp, 576);
dhcp_option_trailer(dhcp);
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_inform: INFORMING\n"));
udp_send(dhcp->pcb, dhcp->p_out);
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
dhcp_delete_request(netif);
} else {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_inform: could not allocate DHCP request\n"));
}
if (dhcp != NULL)
{
if (dhcp->pcb != NULL) udp_remove(dhcp->pcb);
dhcp->pcb = NULL;
mem_free((void *)dhcp);
netif->dhcp = NULL;
}
}
#if DHCP_DOES_ARP_CHECK
/**
* Match an ARP reply with the offered IP address.
*
* @param addr The IP address we received a reply from
*
*/
void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
{
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_arp_reply()\n"));
/* is this DHCP client doing an ARP check? */
if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08lx\n", addr->addr));
/* did a host respond with the address we
were offered by the DHCP server? */
if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
/* we will not accept the offered address */
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE | 1, ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
dhcp_decline(netif);
}
}
}
/**
* Decline an offered lease.
*
* Tell the DHCP server we do not accept the offered address.
* One reason to decline the lease is when we find out the address
* is already in use by another host (through ARP).
*/
static err_t dhcp_decline(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
err_t result = ERR_OK;
u16_t msecs;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_decline()\n"));
dhcp_set_state(dhcp, DHCP_BACKING_OFF);
/* create and initialize the DHCP message header */
result = dhcp_create_request(netif);
if (result == ERR_OK)
{
dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
dhcp_option_byte(dhcp, DHCP_DECLINE);
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
dhcp_option_short(dhcp, 576);
dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
dhcp_option_trailer(dhcp);
/* resize pbuf to reflect true size of options */
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
udp_send(dhcp->pcb, dhcp->p_out);
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
} else {
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_decline: could not allocate DHCP request\n"));
}
dhcp->tries++;
msecs = 10*1000;
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_decline(): set request timeout %u msecs\n", msecs));
return result;
}
#endif
/**
* Start the DHCP process, discover a DHCP server.
*
*/
static err_t dhcp_discover(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
err_t result = ERR_OK;
u16_t msecs;
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_discover()\n"));
ip_addr_set(&dhcp->offered_ip_addr, IP_ADDR_ANY);
/* create and initialize the DHCP message header */
result = dhcp_create_request(netif);
if (result == ERR_OK)
{
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: making request\n"));
dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
dhcp_option_byte(dhcp, DHCP_DISCOVER);
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
dhcp_option_short(dhcp, 576);
dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);
dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
dhcp_option_trailer(dhcp);
LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: realloc()ing\n"));
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
/* set receive callback function with netif as user data */
udp_recv(dhcp->pcb, dhcp_recv, netif);
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -