dhcp.c
来自「Keil下移植好的lwip基于c166」· C语言 代码 · 共 1,329 行 · 第 1/4 页
C
1,329 行
/* did not get response to renew request? */
else if (dhcp->state == DHCP_RENEWING) {
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): RENEWING, DHCP request timed out"));
/* 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) {
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REBINDING, DHCP request timed out"));
if (dhcp->tries <= 8) {
dhcp_rebind(netif);
} else {
DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): RELEASING, DISCOVERING"));
dhcp_release(netif);
dhcp_discover(netif);
}
}
}
/**
* The renewal period has timed out.
*
* @param dhcp pointer to DHCP state structure
*/
static void dhcp_t1_timeout(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
DEBUGF(DHCP_DEBUG, ("dhcp_t1_timeout()"));
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 */
DEBUGF(DHCP_DEBUG, ("dhcp_t1_timeout(): must renew"));
dhcp_renew(netif);
}
}
/**
* The rebind period has timed out.
*
*/
static void dhcp_t2_timeout(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
DEBUGF(DHCP_DEBUG, ("dhcp_t2_timeout()"));
if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
/* just retry to rebind */
DEBUGF(DHCP_DEBUG, ("dhcp_t2_timeout(): must rebind"));
dhcp_rebind(netif);
}
}
/**
* Extract options from the server ACK message.
*
* @param dhcp pointer to DHCP state structure
*/
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);
/* 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 The DHCP client state, which must be passed for
* all subsequential dhcp_*() calls. NULL means there is
* no (longer a) DHCP client attached to the interface
* (due to unavailable memory or network resources).
*
*/
err_t dhcp_start(struct netif *netif)
{
struct dhcp *dhcp = netif->dhcp;
err_t result = ERR_OK;
DEBUGF(DHCP_DEBUG, ("dhcp_start(netif=%c%c%u)", netif->name[0], netif->name[1], netif->num));
if (dhcp == NULL) {
DEBUGF(DHCP_DEBUG, ("dhcp_start(): starting new DHCP client"));
dhcp = mem_malloc(sizeof(struct dhcp));
if (dhcp == NULL) {
DEBUGF(DHCP_DEBUG, ("dhcp_start(): could not allocate dhcp"));
netif->flags &= ~NETIF_FLAG_DHCP;
return ERR_MEM;
}
/* clear data structure */
memset(dhcp, 0, sizeof(struct dhcp));
DEBUGF(DHCP_DEBUG, ("dhcp_start(): allocated dhcp"));
dhcp->pcb = udp_new();
if (dhcp->pcb == NULL) {
DEBUGF(DHCP_DEBUG, ("dhcp_start(): could not obtain pcb"));
mem_free((void *)dhcp);
dhcp = NULL;
netif->flags &= ~NETIF_FLAG_DHCP;
return ERR_MEM;
}
/* store this dhcp client in the netif */
netif->dhcp = dhcp;
DEBUGF(DHCP_DEBUG, ("dhcp_start(): created new udp pcb"));
DEBUGF(DHCP_DEBUG, ("dhcp_start(): starting DHCP configuration"));
} else {
DEBUGF(DHCP_DEBUG, ("dhcp_start(): restarting DHCP configuration"));
}
/* (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) {
DEBUGF(DHCP_DEBUG, ("dhcp_inform(): could not allocate dhcp"));
return;
}
memset(dhcp, 0, sizeof(struct dhcp));
DEBUGF(DHCP_DEBUG, ("dhcp_inform(): allocated dhcp"));
dhcp->pcb = udp_new();
if (dhcp->pcb == NULL) {
DEBUGF(DHCP_DEBUG, ("dhcp_inform(): could not obtain pcb"));
mem_free((void *)dhcp);
return;
}
DEBUGF(DHCP_DEBUG, ("dhcp_inform(): created new udp pcb"));
/* 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);
udp_send(dhcp->pcb, dhcp->p_out);
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
dhcp_delete_request(netif);
}
if (dhcp != NULL)
{
if (dhcp->pcb != NULL) udp_remove(dhcp->pcb);
dhcp->pcb = NULL;
mem_free((void *)dhcp);
}
}
#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)
{
DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply()"));
/* is this DHCP client doing an ARP check? */
if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08lx", 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 */
DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply(): arp reply matched with offered address, declining"));
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;
DEBUGF(DHCP_DEBUG, ("dhcp_decline()"));
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_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);
}
dhcp->tries++;
msecs = 10*1000;
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
DEBUGF(DHCP_DEBUG, ("dhcp_decline(): set request timeout %u msecs", 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;
DEBUGF(DHCP_DEBUG, ("dhcp_discover()"));
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)
{
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);
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_BROADCAST, DHCP_SERVER_PORT);
udp_send(dhcp->pcb, dhcp->p_out);
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
dhcp_delete_request(netif);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?