Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

dhcp.c File Reference

#include "lwip/stats.h"
#include "lwip/mem.h"
#include "lwip/udp.h"
#include "lwip/netif.h"
#include "lwip/inet.h"
#include "lwip/ip_addr.h"
#include "netif/etharp.h"
#include "lwip/sys.h"
#include "lwip/opt.h"
#include "lwip/dhcp.h"

Include dependency graph for dhcp.c:

Go to the source code of this file.

Functions

void dhcp_handle_ack (struct netif *netif)
void dhcp_handle_nak (struct netif *netif)
void dhcp_handle_offer (struct netif *netif)
err_t dhcp_discover (struct netif *netif)
err_t dhcp_select (struct netif *netif)
void dhcp_check (struct netif *netif)
void dhcp_bind (struct netif *netif)
err_t dhcp_decline (struct netif *netif)
err_t dhcp_rebind (struct netif *netif)
err_t dhcp_release (struct netif *netif)
void dhcp_set_state (struct dhcp *dhcp, unsigned char new_state)
void dhcp_recv (void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
err_t dhcp_unfold_reply (struct dhcp *dhcp)
u8_tdhcp_get_option_ptr (struct dhcp *dhcp, u8_t option_type)
u8_t dhcp_get_option_byte (u8_t *ptr)
u16_t dhcp_get_option_short (u8_t *ptr)
u32_t dhcp_get_option_long (u8_t *ptr)
void dhcp_free_reply (struct dhcp *dhcp)
void dhcp_timeout (struct netif *netif)
void dhcp_t1_timeout (struct netif *netif)
void dhcp_t2_timeout (struct netif *netif)
err_t dhcp_create_request (struct netif *netif)
void dhcp_delete_request (struct netif *netif)
void dhcp_option (struct dhcp *dhcp, u8_t option_type, u8_t option_len)
void dhcp_option_byte (struct dhcp *dhcp, u8_t value)
void dhcp_option_short (struct dhcp *dhcp, u16_t value)
void dhcp_option_long (struct dhcp *dhcp, u32_t value)
void dhcp_option_trailer (struct dhcp *dhcp)
void dhcp_coarse_tmr ()
void dhcp_fine_tmr ()
err_t dhcp_start (struct netif *netif)
void dhcp_inform (struct netif *netif)
err_t dhcp_renew (struct netif *netif)
void dhcp_stop (struct netif *netif)

Variables

u32_t xid = 0xABCD0000


Detailed Description

Dynamic Host Configuration Protocol client

Definition in file dhcp.c.


Function Documentation

void dhcp_bind struct netif netif  )  [static]
 

Bind the interface to the offered IP address.

Parameters:
netif network interface to bind to the offered address

Definition at line 721 of file dhcp.c.

References ip_addr::addr, DBG_STATE, DBG_TRACE, DEBUGF, DHCP_BOUND, DHCP_COARSE_TIMER_SECS, DHCP_DEBUG, dhcp_set_state(), htonl, ip4_addr1, ip_addr_set, netif_set_gw(), netif_set_ipaddr(), netif_set_netmask(), and u8_t.

Referenced by dhcp_recv(), and dhcp_timeout().

00722 {
00723   struct dhcp *dhcp = netif->dhcp;
00724   struct ip_addr sn_mask, gw_addr;
00725   
00726   /* temporary DHCP lease? */
00727   if (dhcp->offered_t1_renew != 0xffffffffUL) {
00728     /* set renewal period timer */
00729     DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t1 renewal timer %lu secs\n", dhcp->offered_t1_renew));
00730     dhcp->t1_timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
00731     if (dhcp->t1_timeout == 0) dhcp->t1_timeout = 1;
00732     DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %u msecs\n", dhcp->offered_t1_renew*1000));
00733   }
00734   /* set renewal period timer */
00735   if (dhcp->offered_t2_rebind != 0xffffffffUL) {
00736     DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t2 rebind timer %lu secs\n", dhcp->offered_t2_rebind));
00737     dhcp->t2_timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
00738     if (dhcp->t2_timeout == 0) dhcp->t2_timeout = 1;
00739     DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %u msecs\n", dhcp->offered_t2_rebind*1000));
00740   }
00741   /* copy offered network mask */
00742   ip_addr_set(&sn_mask, &dhcp->offered_sn_mask);
00743 
00744   /* subnet mask not given? */
00745   /* TODO: this is not a valid check. what if the network mask is 0? */
00746   if (sn_mask.addr == 0) {
00747     /* choose a safe subnet mask given the network class */
00748     u8_t first_octet = ip4_addr1(&sn_mask);
00749     if (first_octet <= 127) sn_mask.addr = htonl(0xff000000);
00750     else if (first_octet >= 192) sn_mask.addr = htonl(0xffffff00);
00751     else sn_mask.addr = htonl(0xffff0000);
00752   }
00753 
00754   ip_addr_set(&gw_addr, &dhcp->offered_gw_addr);
00755   /* gateway address not given? */
00756   if (gw_addr.addr == 0) {
00757     /* copy network address */
00758     gw_addr.addr = (dhcp->offered_ip_addr.addr & sn_mask.addr);
00759     /* use first host address on network as gateway */
00760     gw_addr.addr |= htonl(0x00000001);
00761   }
00762 
00763   DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): IP: 0x%08lx\n", dhcp->offered_ip_addr.addr));
00764   netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
00765   DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): SN: 0x%08lx\n", sn_mask.addr));
00766   netif_set_netmask(netif, &sn_mask);
00767   DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): GW: 0x%08lx\n", gw_addr.addr));
00768   netif_set_gw(netif, &gw_addr);
00769   /* netif is now bound to DHCP leased address */
00770   dhcp_set_state(dhcp, DHCP_BOUND);
00771 }

Here is the call graph for this function:

void dhcp_check struct netif netif  )  [static]
 

Checks if the offered IP address is already in use.

It does so by sending an ARP request for the offered address and entering CHECKING state. If no ARP reply is received within a small interval, the address is assumed to be free for use by us.

Definition at line 162 of file dhcp.c.

References DBG_STATE, DBG_TRACE, DEBUGF, DHCP_CHECKING, DHCP_DEBUG, DHCP_FINE_TIMER_MSECS, dhcp_set_state(), ERR_OK, err_t, etharp_query(), NULL, and u16_t.

Referenced by dhcp_recv(), and dhcp_timeout().

00163 {
00164   struct dhcp *dhcp = netif->dhcp;
00165   err_t result;
00166   u16_t msecs;
00167   DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_check()\n"));
00168   /* create an ARP query for the offered IP address, expecting that no host
00169      responds, as the IP address should not be in use. */
00170   result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
00171   if (result != ERR_OK) {
00172     DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_check: could not perform ARP query\n"));
00173   }
00174   dhcp->tries++;
00175   msecs = 500;
00176   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00177   DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_check(): set request timeout %u msecs\n", msecs));
00178   dhcp_set_state(dhcp, DHCP_CHECKING);
00179 }

Here is the call graph for this function:

void dhcp_coarse_tmr void   ) 
 

The DHCP timer that checks for lease renewal/rebind timeouts.

Definition at line 268 of file dhcp.c.

References DBG_STATE, DBG_TRACE, DEBUGF, DHCP_DEBUG, dhcp_t1_timeout(), dhcp_t2_timeout(), netif_list, and NULL.

00269 {
00270   struct netif *netif = netif_list;
00271   DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_coarse_tmr()\n"));
00272   /* iterate through all network interfaces */
00273   while (netif != NULL) {
00274     /* only act on DHCP configured interfaces */
00275     if (netif->dhcp != NULL) {
00276       /* timer is active (non zero), and triggers (zeroes) now? */
00277       if (netif->dhcp->t2_timeout-- == 1) {
00278         DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n"));
00279         /* this clients' rebind timeout triggered */
00280         dhcp_t2_timeout(netif);
00281       /* timer is active (non zero), and triggers (zeroes) now */
00282       } else if (netif->dhcp->t1_timeout-- == 1) {
00283         DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n"));
00284         /* this clients' renewal timeout triggered */
00285         dhcp_t1_timeout(netif);
00286       }
00287     }
00288     /* proceed to next netif */
00289     netif = netif->next;
00290   }
00291 }

Here is the call graph for this function:

err_t dhcp_create_request struct netif netif  )  [static]
 

create a DHCP request, fill in common headers

Definition at line 1188 of file dhcp.c.

References ip_addr::addr, DBG_TRACE, DEBUGF, DHCP_BOOTREQUEST, DHCP_CHADDR_LEN, DHCP_DEBUG, DHCP_FILE_LEN, DHCP_HLEN_ETH, DHCP_HTYPE_ETH, DHCP_OPTIONS_LEN, DHCP_SNAME_LEN, ERR_MEM, ERR_OK, err_t, htonl, netif::hwaddr, netif::hwaddr_len, netif::ip_addr, LWIP_ASSERT, NULL, pbuf_alloc(), PBUF_RAM, PBUF_TRANSPORT, u16_t, and xid.

Referenced by dhcp_discover(), dhcp_inform(), dhcp_rebind(), dhcp_release(), dhcp_renew(), and dhcp_select().

01189 {
01190   struct dhcp *dhcp = netif->dhcp;
01191   u16_t i;
01192   LWIP_ASSERT("dhcp_create_request: dhcp->p_out == NULL", dhcp->p_out == NULL);
01193   LWIP_ASSERT("dhcp_create_request: dhcp->msg_out == NULL", dhcp->msg_out == NULL);
01194   dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
01195   if (dhcp->p_out == NULL) {
01196     DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_create_request(): could not allocate pbuf\n"));
01197     return ERR_MEM;
01198   }
01199   /* give unique transaction identifier to this request */
01200   dhcp->xid = xid++;  
01201 
01202   dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload;
01203 
01204   dhcp->msg_out->op = DHCP_BOOTREQUEST;
01205   /* TODO: make link layer independent */  
01206   dhcp->msg_out->htype = DHCP_HTYPE_ETH;  
01207   /* TODO: make link layer independent */  
01208   dhcp->msg_out->hlen = DHCP_HLEN_ETH;  
01209   dhcp->msg_out->hops = 0;
01210   dhcp->msg_out->xid = htonl(dhcp->xid);  
01211   dhcp->msg_out->secs = 0;
01212   dhcp->msg_out->flags = 0;
01213   dhcp->msg_out->ciaddr = netif->ip_addr.addr;
01214   dhcp->msg_out->yiaddr = 0;
01215   dhcp->msg_out->siaddr = 0;
01216   dhcp->msg_out->giaddr = 0;
01217   for (i = 0; i < DHCP_CHADDR_LEN; i++) {
01218     /* copy netif hardware address, pad with zeroes */
01219     dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0/* pad byte*/;
01220   }
01221   for (i = 0; i < DHCP_SNAME_LEN; i++) dhcp->msg_out->sname[i] = 0;
01222   for (i = 0; i < DHCP_FILE_LEN; i++) dhcp->msg_out->file[i] = 0;
01223   dhcp->msg_out->cookie = htonl(0x63825363UL);
01224   dhcp->options_out_len = 0;
01225   /* fill options field with an incrementing array (for debugging purposes) */
01226   for (i = 0; i < DHCP_OPTIONS_LEN; i++) dhcp->msg_out->options[i] = i;
01227   return ERR_OK;
01228 }

Here is the call graph for this function:

err_t dhcp_decline struct netif netif  )  [static]
 

void dhcp_delete_request struct netif netif  )  [static]
 

free a DHCP request

Definition at line 1230 of file dhcp.c.

References LWIP_ASSERT, NULL, and pbuf_free().

Referenced by dhcp_discover(), dhcp_inform(), dhcp_rebind(), dhcp_release(), dhcp_renew(), and dhcp_select().

01231 {
01232   struct dhcp *dhcp = netif->dhcp;
01233   LWIP_ASSERT("dhcp_free_msg: dhcp->p_out != NULL", dhcp->p_out != NULL);
01234   LWIP_ASSERT("dhcp_free_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL);
01235   pbuf_free(dhcp->p_out);
01236   dhcp->p_out = NULL;
01237   dhcp->msg_out = NULL;
01238 }

Here is the call graph for this function:

err_t dhcp_discover struct netif netif  )  [static]
 

Start the DHCP process, discover a DHCP server.

Definition at line 661 of file dhcp.c.

References DBG_STATE, DBG_TRACE, DEBUGF, DHCP_CLIENT_PORT, dhcp_create_request(), DHCP_DEBUG, dhcp_delete_request(), DHCP_DISCOVER, DHCP_FINE_TIMER_MSECS, dhcp_option(), DHCP_OPTION_BROADCAST, dhcp_option_byte(), DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, DHCP_OPTION_PARAMETER_REQUEST_LIST, DHCP_OPTION_ROUTER, dhcp_option_short(), DHCP_OPTION_SUBNET_MASK, dhcp_option_trailer(), DHCP_OPTIONS_LEN, dhcp_recv(), DHCP_SELECTING, DHCP_SERVER_PORT, dhcp_set_state(), ERR_OK, err_t, IP_ADDR_ANY, IP_ADDR_BROADCAST, ip_addr_set, pbuf_realloc(), u16_t, udp_bind(), udp_connect(), udp_recv(), and udp_send().

Referenced by dhcp_start(), and dhcp_timeout().

00662 {
00663   struct dhcp *dhcp = netif->dhcp;
00664   err_t result = ERR_OK;
00665   u16_t msecs;
00666   DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_discover()\n"));
00667   ip_addr_set(&dhcp->offered_ip_addr, IP_ADDR_ANY);
00668   /* create and initialize the DHCP message header */
00669   result = dhcp_create_request(netif);
00670   if (result == ERR_OK)
00671   {
00672     DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: making request\n"));
00673     dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
00674     dhcp_option_byte(dhcp, DHCP_DISCOVER);
00675 
00676     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00677     dhcp_option_short(dhcp, 576);
00678 
00679     dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);
00680     dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
00681     dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
00682     dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
00683 
00684     dhcp_option_trailer(dhcp);
00685 
00686     DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: realloc()ing\n"));
00687     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00688 
00689     /* set receive callback function with netif as user data */
00690     udp_recv(dhcp->pcb, dhcp_recv, netif);
00691     udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00692     udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
00693 
00694     DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: send()ing\n"));
00695 
00696     udp_send(dhcp->pcb, dhcp->p_out);
00697     DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: bind()ing\n"));
00698     udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00699     DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: connect()ing\n"));
00700     udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
00701     DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
00702     dhcp_delete_request(netif);
00703     DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover: SELECTING\n"));
00704     dhcp_set_state(dhcp, DHCP_SELECTING);
00705   } else {
00706     DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_discover: could not allocate DHCP request\n"));
00707   }
00708   dhcp->tries++;
00709   msecs = dhcp->tries < 4 ? (dhcp->tries + 1) * 1000 : 10 * 1000;
00710   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00711   DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover(): set request timeout %u msecs\n", msecs));
00712   return result;
00713 }

Here is the call graph for this function:

void dhcp_fine_tmr void   ) 
 

DHCP transaction timeout handling

A DHCP server is expected to respond within a short period of time.

Definition at line 299 of file dhcp.c.

References DBG_STATE, DBG_TRACE, DEBUGF, DHCP_DEBUG, dhcp_timeout(), netif_list, and NULL.

00300 {
00301   struct netif *netif = netif_list;
00302   /* loop through clients */
00303   while (netif != NULL) {
00304     /* only act on DHCP configured interfaces */
00305     if (netif->dhcp != NULL) {
00306       /* timer is active (non zero), and triggers (zeroes) now */
00307       if (netif->dhcp->request_timeout-- == 1) {
00308         DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
00309         /* this clients' request timeout triggered */
00310         dhcp_timeout(netif);
00311       }
00312     }
00313     /* proceed to next network interface */
00314     netif = netif->next;
00315   }
00316 }

Here is the call graph for this function:

void dhcp_free_reply struct dhcp dhcp  )  [static]
 

Free the incoming DHCP message including contiguous copy of its DHCP options.

Definition at line 1081 of file dhcp.c.

References DEBUGF, DHCP_DEBUG, mem_free(), dhcp::msg_in, NULL, dhcp::options_in, and dhcp::options_in_len.

Referenced by dhcp_stop(), and dhcp_unfold_reply().

01082 {
01083   if (dhcp->msg_in != NULL) {
01084     mem_free((void *)dhcp->msg_in);
01085     dhcp->msg_in = NULL;
01086   }
01087   if (dhcp->options_in) {
01088     mem_free((void *)dhcp->options_in);
01089     dhcp->options_in = NULL;
01090     dhcp->options_in_len = 0;
01091   }
01092   DEBUGF(DHCP_DEBUG, ("dhcp_free_reply(): free'd\n")); 
01093 }

Here is the call graph for this function:

u8_t dhcp_get_option_byte u8_t ptr  )  [static]
 

Return the byte of DHCP option data.

Parameters:
client DHCP client.
ptr pointer obtained by dhcp_get_option_ptr().
Returns:
byte value at the given address.

Definition at line 1347 of file dhcp.c.

References DEBUGF, DHCP_DEBUG, and u8_t.

Referenced by dhcp_recv().

01348 {
01349   DEBUGF(DHCP_DEBUG, ("option byte value=%u\n", *ptr));
01350   return *ptr;
01351 }                             

u32_t dhcp_get_option_long u8_t ptr  )  [static]
 

Return the 32-bit value of DHCP option data.

Parameters:
client DHCP client.
ptr pointer obtained by dhcp_get_option_ptr().
Returns:
byte value at the given address.

Definition at line 1378 of file dhcp.c.

References DEBUGF, DHCP_DEBUG, u32_t, and u8_t.

Referenced by dhcp_handle_ack(), and dhcp_handle_offer().

01379 {
01380   u32_t value;
01381   value = (u32_t)(*ptr++) << 24;
01382   value |= (u32_t)(*ptr++) << 16;
01383   value |= (u32_t)(*ptr++) << 8;
01384   value |= (u32_t)(*ptr++);
01385   DEBUGF(DHCP_DEBUG, ("option long value=%lu\n", value));
01386   return value;
01387 }                             

u8_t * dhcp_get_option_ptr struct dhcp dhcp,
u8_t  option_type
[static]
 

Find the offset of a DHCP option inside the DHCP message.

Parameters:
client DHCP client
option_type 
Returns:
a byte offset into the UDP message where the option was found, or zero if the given option was not found.

Definition at line 1270 of file dhcp.c.

References DBG_TRACE, DEBUGF, DHCP_DEBUG, DHCP_FILE_LEN, DHCP_OPTION_END, DHCP_OPTION_OVERLOAD, DHCP_OVERLOAD_FILE, DHCP_OVERLOAD_NONE, DHCP_OVERLOAD_SNAME, DHCP_SNAME_LEN, dhcp::msg_in, NULL, dhcp::options_in, dhcp::options_in_len, u16_t, and u8_t.

Referenced by dhcp_handle_ack(), dhcp_handle_offer(), and dhcp_recv().

01271 {
01272   u8_t overload = DHCP_OVERLOAD_NONE;
01273 
01274   /* options available? */
01275   if ((dhcp->options_in != NULL) && (dhcp->options_in_len > 0)) {
01276     /* start with options field */
01277     u8_t *options = (u8_t *)dhcp->options_in;
01278     u16_t offset = 0;
01279     /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
01280     while ((offset < dhcp->options_in_len) && (options[offset] != DHCP_OPTION_END)) {
01281       /* DEBUGF(DHCP_DEBUG, ("msg_offset=%u, q->len=%u", msg_offset, q->len)); */
01282       /* are the sname and/or file field overloaded with options? */
01283       if (options[offset] == DHCP_OPTION_OVERLOAD) {
01284         DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("overloaded message detected\n"));
01285         /* skip option type and length */
01286         offset += 2;
01287         overload = options[offset++];
01288       }
01289       /* requested option found */
01290       else if (options[offset] == option_type) {
01291         DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset %u in options\n", offset));
01292         return &options[offset];
01293       /* skip option */
01294       } else {
01295          DEBUGF(DHCP_DEBUG, ("skipping option %u in options\n", options[offset]));
01296         /* skip option type */
01297         offset++;
01298         /* skip option length, and then length bytes */
01299         offset += 1 + options[offset];
01300       }
01301     }
01302     /* is this an overloaded message? */
01303     if (overload != DHCP_OVERLOAD_NONE) {
01304       u16_t field_len;
01305       if (overload == DHCP_OVERLOAD_FILE) {
01306         DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("overloaded file field\n"));
01307         options = (u8_t *)&dhcp->msg_in->file;
01308         field_len = DHCP_FILE_LEN;
01309       } else if (overload == DHCP_OVERLOAD_SNAME) {
01310         DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("overloaded sname field\n"));
01311         options = (u8_t *)&dhcp->msg_in->sname;
01312         field_len = DHCP_SNAME_LEN;
01313       /* TODO: check if else if () is necessary */
01314       } else {
01315         DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("overloaded sname and file field\n"));
01316         options = (u8_t *)&dhcp->msg_in->sname;
01317         field_len = DHCP_FILE_LEN + DHCP_SNAME_LEN;
01318       }
01319       offset = 0;
01320 
01321       /* at least 1 byte to read and no end marker */
01322       while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) {
01323         if (options[offset] == option_type) {
01324            DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset=%u\n", offset));
01325           return &options[offset];
01326         /* skip option */
01327         } else {
01328           DEBUGF(DHCP_DEBUG | DBG_TRACE, ("skipping option %u\n", options[offset]));
01329           /* skip option type */
01330           offset++;
01331           offset += 1 + options[offset];
01332         }
01333       }
01334     }
01335   }
01336   return 0;
01337 }

u16_t dhcp_get_option_short u8_t ptr  )  [static]
 

Return the 16-bit value of DHCP option data.

Parameters:
client DHCP client.
ptr pointer obtained by dhcp_get_option_ptr().
Returns:
byte value at the given address.

Definition at line 1361 of file dhcp.c.

References DEBUGF, DHCP_DEBUG, u16_t, and u8_t.

01362 {
01363   u16_t value;
01364   value = *ptr++ << 8;
01365   value |= *ptr;
01366   DEBUGF(DHCP_DEBUG, ("option short value=%u\n", value));
01367   return value;
01368 }                             

void dhcp_handle_ack struct netif netif  )  [static]
 

Extract options from the server ACK message.

Parameters:
netif the netif under DHCP control

Definition at line 413 of file dhcp.c.

References dhcp_get_option_long(), dhcp_get_option_ptr(), DHCP_OPTION_BROADCAST, DHCP_OPTION_LEASE_TIME, DHCP_OPTION_ROUTER, DHCP_OPTION_SUBNET_MASK, DHCP_OPTION_T1, DHCP_OPTION_T2, htonl, ip_addr_set, NULL, and u8_t.

Referenced by dhcp_recv().

00414 {
00415   struct dhcp *dhcp = netif->dhcp;
00416   u8_t *option_ptr;
00417   /* clear options we might not get from the ACK */
00418   dhcp->offered_sn_mask.addr = 0;
00419   dhcp->offered_gw_addr.addr = 0;
00420   dhcp->offered_bc_addr.addr = 0;
00421 
00422   /* lease time given? */
00423   option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_LEASE_TIME);
00424   if (option_ptr != NULL) {
00425     /* remember offered lease time */
00426     dhcp->offered_t0_lease = dhcp_get_option_long(option_ptr + 2);
00427   }
00428   /* renewal period given? */
00429   option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T1);
00430   if (option_ptr != NULL) {
00431     /* remember given renewal period */
00432     dhcp->offered_t1_renew = dhcp_get_option_long(option_ptr + 2);
00433   } else {
00434     /* calculate safe periods for renewal */
00435     dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2;
00436   }
00437 
00438   /* renewal period given? */
00439   option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T2);
00440   if (option_ptr != NULL) {
00441     /* remember given rebind period */
00442     dhcp->offered_t2_rebind = dhcp_get_option_long(option_ptr + 2);
00443   } else {
00444     /* calculate safe periods for rebinding */
00445     dhcp->offered_t2_rebind = dhcp->offered_t0_lease;
00446   }
00447 
00448   /* (y)our internet address */
00449   ip_addr_set(&dhcp->offered_ip_addr, &dhcp->msg_in->yiaddr);
00450 
00451   /* subnet mask */
00452   option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SUBNET_MASK);
00453   /* subnet mask given? */
00454   if (option_ptr != NULL) {
00455     dhcp->offered_sn_mask.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
00456   }
00457 
00458   /* gateway router */
00459   option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_ROUTER);
00460   if (option_ptr != NULL) {
00461     dhcp->offered_gw_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
00462   }
00463 
00464   /* broadcast address */
00465   option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_BROADCAST);
00466   if (option_ptr != NULL) {
00467     dhcp->offered_bc_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
00468   }
00469 }

Here is the call graph for this function:

void dhcp_handle_nak struct netif netif  )  [static]
 

Back-off the DHCP client (because of a received NAK response).

Back-off the DHCP client because of a received NAK. Receiving a NAK means the client asked for something non-sensible, for example when it tries to renew a lease obtained on another network.

We back-off and will end up restarting a fresh DHCP negotiation later.

Parameters:
state pointer to DHCP state structure

Definition at line 146 of file dhcp.c.

References DBG_STATE, DBG_TRACE, DEBUGF, DHCP_BACKING_OFF, DHCP_DEBUG, DHCP_FINE_TIMER_MSECS, dhcp_set_state(), and u16_t.

Referenced by dhcp_recv().

00146                                                  {
00147   struct dhcp *dhcp = netif->dhcp;
00148   u16_t msecs = 10 * 1000;
00149   DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_handle_nak()\n"));
00150   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00151   DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_handle_nak(): set request timeout %u msecs\n", msecs));
00152   dhcp_set_state(dhcp, DHCP_BACKING_OFF);
00153 }

Here is the call graph for this function:

void dhcp_handle_offer struct netif netif  )  [static]
 

Remember the configuration offered by a DHCP server.

Parameters:
state pointer to DHCP state structure

Definition at line 186 of file dhcp.c.

References DBG_STATE, DEBUGF, DHCP_DEBUG, dhcp_get_option_long(), dhcp_get_option_ptr(), DHCP_OPTION_SERVER_ID, dhcp_select(), htonl, ip_addr_set, NULL, and u8_t.

Referenced by dhcp_recv().

00187 {
00188   struct dhcp *dhcp = netif->dhcp;
00189   /* obtain the server address */
00190   u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID);
00191   if (option_ptr != NULL)
00192   {
00193     dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
00194     DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): server 0x%08lx\n", dhcp->server_ip_addr.addr));
00195     /* remember offered address */
00196     ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr);
00197     DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08lx\n", dhcp->offered_ip_addr.addr));
00198     dhcp_select(netif);
00199   }
00200 }

Here is the call graph for this function:

void dhcp_inform struct netif netif  ) 
 

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.

Parameters:
netif The lwIP network interface

Definition at line 537 of file dhcp.c.

References DBG_STATE, DBG_TRACE, DEBUGF, DHCP_CLIENT_PORT, dhcp_create_request(), DHCP_DEBUG, dhcp_delete_request(), DHCP_INFORM, dhcp_option(), dhcp_option_byte(), DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, dhcp_option_short(), dhcp_option_trailer(), DHCP_OPTIONS_LEN, DHCP_SERVER_PORT, ERR_OK, err_t, IP_ADDR_ANY, IP_ADDR_BROADCAST, mem_free(), mem_malloc(), NULL, pbuf_realloc(), udp_bind(), udp_connect(), udp_new(), udp_remove(), and udp_send().

00538 {
00539   struct dhcp *dhcp;
00540   err_t result = ERR_OK;
00541   dhcp = mem_malloc(sizeof(struct dhcp));
00542   if (dhcp == NULL) {
00543     DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_inform(): could not allocate dhcp\n"));
00544     return;
00545   }  
00546   memset(dhcp, 0, sizeof(struct dhcp));
00547 
00548   DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_inform(): allocated dhcp\n"));
00549   dhcp->pcb = udp_new();
00550   if (dhcp->pcb == NULL) {
00551     DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_inform(): could not obtain pcb"));
00552     mem_free((void *)dhcp);
00553     return;
00554   }
00555   DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_inform(): created new udp pcb\n"));
00556   /* create and initialize the DHCP message header */
00557   result = dhcp_create_request(netif);
00558   if (result == ERR_OK) {
00559 
00560     dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
00561     dhcp_option_byte(dhcp, DHCP_INFORM);
00562 
00563     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00564     /* TODO: use netif->mtu ?! */
00565     dhcp_option_short(dhcp, 576);
00566 
00567     dhcp_option_trailer(dhcp);
00568 
00569     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00570 
00571     udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00572     udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
00573     DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_inform: INFORMING\n"));
00574     udp_send(dhcp->pcb, dhcp->p_out);
00575     udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
00576     dhcp_delete_request(netif);
00577   } else {
00578     DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_inform: could not allocate DHCP request\n"));
00579   }
00580 
00581   if (dhcp != NULL)
00582   {
00583     if (dhcp->pcb != NULL) udp_remove(dhcp->pcb);
00584     dhcp->pcb = NULL;
00585     mem_free((void *)dhcp);
00586   }
00587 }

Here is the call graph for this function:

void dhcp_option struct dhcp dhcp,
u8_t  option_type,
u8_t  option_len
[static]
 

add a DHCP option (type, then length in bytes)

Definition at line 975 of file dhcp.c.

References DHCP_OPTIONS_LEN, LWIP_ASSERT, dhcp::msg_out, dhcp::options_out_len, and u8_t.

Referenced by dhcp_discover(), dhcp_inform(), dhcp_rebind(), dhcp_release(), dhcp_renew(), and dhcp_select().

00976 {
00977   LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN);
00978   dhcp->msg_out->options[dhcp->options_out_len++] = option_type;
00979   dhcp->msg_out->options[dhcp->options_out_len++] = option_len;
00980 }

void dhcp_option_byte struct dhcp dhcp,
u8_t  value
[static]
 

add option values

Definition at line 985 of file dhcp.c.

References DHCP_OPTIONS_LEN, LWIP_ASSERT, dhcp::msg_out, dhcp::options_out_len, and u8_t.

Referenced by dhcp_discover(), dhcp_inform(), dhcp_rebind(), dhcp_release(), dhcp_renew(), and dhcp_select().

00986 {
00987   LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN);
00988   dhcp->msg_out->options[dhcp->options_out_len++] = value;
00989 }                             

void dhcp_option_long struct dhcp dhcp,
u32_t  value
[static]
 

Definition at line 996 of file dhcp.c.

References DHCP_OPTIONS_LEN, LWIP_ASSERT, dhcp::msg_out, dhcp::options_out_len, and u32_t.

Referenced by dhcp_rebind(), dhcp_renew(), and dhcp_select().

00997 {
00998   LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN);
00999   dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0xff000000UL) >> 24;
01000   dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0x00ff0000UL) >> 16;
01001   dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0x0000ff00UL) >> 8;
01002   dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0x000000ffUL);
01003 }

void dhcp_option_short struct dhcp dhcp,
u16_t  value
[static]
 

Definition at line 990 of file dhcp.c.

References DHCP_OPTIONS_LEN, LWIP_ASSERT, dhcp::msg_out, dhcp::options_out_len, and u16_t.

Referenced by dhcp_discover(), dhcp_inform(), dhcp_rebind(), dhcp_renew(), and dhcp_select().

00991 {
00992   LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN);
00993   dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0xff00U) >> 8;
00994   dhcp->msg_out->options[dhcp->options_out_len++] =  value & 0x00ffU;
00995 }

void dhcp_option_trailer struct dhcp dhcp  )  [static]
 

Add a DHCP message trailer

Adds the END option to the DHCP message, and if necessary, up to three padding bytes.

Definition at line 1247 of file dhcp.c.

References DHCP_MIN_OPTIONS_LEN, DHCP_OPTION_END, DHCP_OPTIONS_LEN, LWIP_ASSERT, dhcp::msg_out, NULL, and dhcp::options_out_len.

Referenced by dhcp_discover(), dhcp_inform(), dhcp_rebind(), dhcp_release(), dhcp_renew(), and dhcp_select().

01248 {
01249   LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL);
01250   LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
01251   dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
01252   /* packet is too small, or not 4 byte aligned? */
01253   while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) {
01254     /* DEBUGF(DHCP_DEBUG, ("dhcp_option_trailer: dhcp->options_out_len=%u, DHCP_OPTIONS_LEN=%u", dhcp->options_out_len, DHCP_OPTIONS_LEN)); */
01255     LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
01256     /* add a fill/padding byte */
01257     dhcp->msg_out->options[dhcp->options_out_len++] = 0;
01258   }
01259 }

err_t dhcp_rebind struct netif netif  )  [static]
 

Rebind with a DHCP server for an existing DHCP lease.

Parameters:
netif network interface which must rebind with a DHCP server

Definition at line 833 of file dhcp.c.

References DBG_STATE, DBG_TRACE, DEBUGF, DHCP_CLIENT_PORT, dhcp_create_request(), DHCP_DEBUG, dhcp_delete_request(), DHCP_FINE_TIMER_MSECS, dhcp_option(), dhcp_option_byte(), dhcp_option_long(), DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, DHCP_OPTION_REQUESTED_IP, DHCP_OPTION_SERVER_ID, dhcp_option_short(), dhcp_option_trailer(), DHCP_OPTIONS_LEN, DHCP_REBINDING, DHCP_REQUEST, DHCP_SERVER_PORT, dhcp_set_state(), ERR_OK, err_t, IP_ADDR_ANY, IP_ADDR_BROADCAST, ntohl, pbuf_realloc(), u16_t, udp_bind(), udp_connect(), and udp_send().

Referenced by dhcp_t2_timeout(), and dhcp_timeout().

00834 {
00835   struct dhcp *dhcp = netif->dhcp;
00836   err_t result;
00837   u16_t msecs;
00838   DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind()\n"));
00839   dhcp_set_state(dhcp, DHCP_REBINDING);
00840 
00841   /* create and initialize the DHCP message header */
00842   result = dhcp_create_request(netif);
00843   if (result == ERR_OK)
00844   {
00845 
00846     dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
00847     dhcp_option_byte(dhcp, DHCP_REQUEST);
00848 
00849     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00850     dhcp_option_short(dhcp, 576);
00851 
00852 #if 0
00853     dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
00854     dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
00855 
00856     dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
00857     dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
00858 #endif
00859 
00860     dhcp_option_trailer(dhcp);
00861 
00862     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00863 
00864     udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00865     udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
00866     udp_send(dhcp->pcb, dhcp->p_out);
00867     udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
00868     dhcp_delete_request(netif);
00869     DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind: REBINDING\n"));
00870   } else {
00871     DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_rebind: could not allocate DHCP request\n"));
00872   }
00873   dhcp->tries++;
00874   msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
00875   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00876    DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind(): set request timeout %u msecs\n", msecs));
00877   return result;
00878 }

Here is the call graph for this function:

void dhcp_recv void *  arg,
struct udp_pcb pcb,
struct pbuf p,
struct ip_addr addr,
u16_t  port
[static]
 

If an incoming DHCP message is in response to use, then trigger the state machine

Definition at line 1099 of file dhcp.c.

References DBG_TRACE, DEBUGF, DHCP_ACK, dhcp_bind(), DHCP_BOOTREPLY, dhcp_check(), DHCP_DEBUG, dhcp_get_option_byte(), dhcp_get_option_ptr(), dhcp_handle_ack(), dhcp_handle_nak(), dhcp_handle_offer(), DHCP_NAK, DHCP_OFFER, DHCP_OPTION_MESSAGE_TYPE, DHCP_REBINDING, DHCP_REBOOTING, DHCP_RENEWING, DHCP_REQUESTING, DHCP_SELECTING, dhcp_unfold_reply(), ERR_OK, netif::hwaddr, netif::hwaddr_len, pbuf::len, ntohl, NULL, pbuf::payload, pbuf_free(), pbuf::tot_len, u16_t, and u8_t.

Referenced by dhcp_discover().

01100 {
01101   struct netif *netif = (struct netif *)arg;
01102   struct dhcp *dhcp = netif->dhcp;
01103   struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload;
01104   u8_t *options_ptr;
01105   u8_t msg_type;
01106   u8_t i;
01107   DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_recv()\n"));
01108   DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->len = %u\n", p->len));
01109   DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->tot_len = %u\n", p->tot_len));
01110   dhcp->p = p;
01111   if (reply_msg->op != DHCP_BOOTREPLY) {
01112     DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("not a DHCP reply message, but type %u\n", reply_msg->op));
01113     pbuf_free(p);
01114   }
01115   /* iterate through hardware address and match against DHCP message */
01116   for (i = 0; i < netif->hwaddr_len; i++) {
01117     if (netif->hwaddr[i] != reply_msg->chaddr[i]) { 
01118       DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("netif->hwaddr[%u]==%02x != reply_msg->chaddr[%u]==%02x\n",
01119         i, netif->hwaddr[i], i, reply_msg->chaddr[i]));
01120       pbuf_free(p);
01121       return;
01122     }
01123   }
01124   /* match transaction ID against what we expected */
01125   if (ntohl(reply_msg->xid) != dhcp->xid) {
01126     DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("transaction id mismatch\n"));
01127     pbuf_free(p);
01128     return;
01129   }
01130   /* option fields could be unfold? */
01131   if (dhcp_unfold_reply(dhcp) != ERR_OK) {
01132     DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("problem unfolding DHCP message - too short on memory?\n"));
01133     pbuf_free(p);
01134     return;
01135   }
01136   
01137   DEBUGF(DHCP_DEBUG | DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n"));
01138   /* obtain pointer to DHCP message type */ 
01139   options_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_MESSAGE_TYPE);
01140   if (options_ptr == NULL) {
01141     DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("DHCP_OPTION_MESSAGE_TYPE option not found\n")); 
01142     pbuf_free(p);
01143     return;
01144   }  
01145 
01146   /* read DHCP message type */
01147   msg_type = dhcp_get_option_byte(options_ptr + 2);
01148   /* message type is DHCP ACK? */
01149   if (msg_type == DHCP_ACK) {
01150     DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("DHCP_ACK received\n")); 
01151     /* in requesting state? */
01152     if (dhcp->state == DHCP_REQUESTING) {
01153       dhcp_handle_ack(netif);
01154       dhcp->request_timeout = 0;
01155 #if DHCP_DOES_ARP_CHECK
01156       /* check if the acknowledged lease address is already in use */
01157       dhcp_check(netif);
01158 #else
01159       /* bind interface to the acknowledged lease address */
01160       dhcp_bind(netif);
01161 #endif
01162     }
01163     /* already bound to the given lease address? */
01164     else if ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING)) {
01165       dhcp->request_timeout = 0;
01166       dhcp_bind(netif);
01167     }
01168   }
01169   /* received a DHCP_NAK in appropriate state? */
01170   else if ((msg_type == DHCP_NAK) &&
01171     ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) || 
01172      (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING  ))) {
01173     DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("DHCP_NAK received\n")); 
01174     dhcp->request_timeout = 0;
01175     dhcp_handle_nak(netif);
01176   }
01177   /* received a DHCP_OFFER in DHCP_SELECTING state? */
01178   else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) {
01179     DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("DHCP_OFFER received in DHCP_SELECTING state\n")); 
01180     dhcp->request_timeout = 0;
01181     /* remember offered lease */
01182     dhcp_handle_offer(netif);
01183   }
01184   pbuf_free(p);
01185 }

Here is the call graph for this function:

err_t dhcp_release struct netif netif  )  [static]
 

Release a DHCP lease.

Parameters:
netif network interface which must release its lease

Definition at line 885 of file dhcp.c.

References DBG_STATE, DBG_TRACE, DEBUGF, DHCP_CLIENT_PORT, dhcp_create_request(), DHCP_DEBUG, dhcp_delete_request(), DHCP_FINE_TIMER_MSECS, DHCP_OFF, dhcp_option(), dhcp_option_byte(), DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, dhcp_option_trailer(), DHCP_OPTIONS_LEN, DHCP_RELEASE, DHCP_SERVER_PORT, dhcp_set_state(), ERR_OK, err_t, IP_ADDR_ANY, netif_set_gw(), netif_set_ipaddr(), netif_set_netmask(), pbuf_realloc(), u16_t, udp_bind(), udp_connect(), and udp_send().

Referenced by dhcp_timeout().

00886 {
00887   struct dhcp *dhcp = netif->dhcp;
00888   err_t result;
00889   u16_t msecs;
00890   DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_release()\n"));
00891 
00892   /* idle DHCP client */
00893   dhcp_set_state(dhcp, DHCP_OFF);
00894 
00895 
00896   /* create and initialize the DHCP message header */
00897   result = dhcp_create_request(netif);
00898   if (result == ERR_OK) {
00899     dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
00900     dhcp_option_byte(dhcp, DHCP_RELEASE);
00901 
00902     dhcp_option_trailer(dhcp);
00903 
00904     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00905 
00906     udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00907     udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
00908     udp_send(dhcp->pcb, dhcp->p_out);
00909     dhcp_delete_request(netif);
00910     DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n"));
00911   } else {
00912     DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_release: could not allocate DHCP request\n"));
00913   }
00914   dhcp->tries++;
00915   msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
00916   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00917    DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release(): set request timeout %u msecs\n", msecs));
00918   /* remove IP address from interface */
00919   netif_set_ipaddr(netif, IP_ADDR_ANY);
00920   netif_set_gw(netif, IP_ADDR_ANY);
00921   netif_set_netmask(netif, IP_ADDR_ANY);
00922   /* TODO: netif_down(netif); */
00923   return result;
00924 }

Here is the call graph for this function:

err_t dhcp_renew struct netif netif  ) 
 

Renew an existing DHCP lease at the involved DHCP server.

Parameters:
netif network interface which must renew its lease

Definition at line 778 of file dhcp.c.

References DBG_STATE, DBG_TRACE, DEBUGF, DHCP_CLIENT_PORT, dhcp_create_request(), DHCP_DEBUG, dhcp_delete_request(), DHCP_FINE_TIMER_MSECS, dhcp_option(), dhcp_option_byte(), dhcp_option_long(), DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, DHCP_OPTION_REQUESTED_IP, DHCP_OPTION_SERVER_ID, dhcp_option_short(), dhcp_option_trailer(), DHCP_OPTIONS_LEN, DHCP_RENEWING, DHCP_REQUEST, DHCP_SERVER_PORT, dhcp_set_state(), ERR_OK, err_t, IP_ADDR_ANY, ntohl, pbuf_realloc(), u16_t, udp_bind(), udp_connect(), and udp_send().

Referenced by dhcp_t1_timeout(), and dhcp_timeout().

00779 {
00780   struct dhcp *dhcp = netif->dhcp;
00781   err_t result;
00782   u16_t msecs;
00783   DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_renew()\n"));
00784   dhcp_set_state(dhcp, DHCP_RENEWING);
00785 
00786   /* create and initialize the DHCP message header */
00787   result = dhcp_create_request(netif);
00788   if (result == ERR_OK) {
00789 
00790     dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
00791     dhcp_option_byte(dhcp, DHCP_REQUEST);
00792 
00793     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00794     /* TODO: use netif->mtu in some way */
00795     dhcp_option_short(dhcp, 576);
00796 
00797 #if 0
00798     dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
00799     dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
00800 #endif
00801 
00802 #if 0
00803     dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
00804     dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
00805 #endif
00806     /* append DHCP message trailer */
00807     dhcp_option_trailer(dhcp);
00808 
00809     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00810 
00811     udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00812     udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
00813     udp_send(dhcp->pcb, dhcp->p_out);
00814     dhcp_delete_request(netif);
00815 
00816     DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_renew: RENEWING\n"));
00817   } else {
00818     DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_renew: could not allocate DHCP request\n"));
00819   }
00820   dhcp->tries++;
00821   /* back-off on retries, but to a maximum of 20 seconds */
00822   msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
00823   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00824    DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_renew(): set request timeout %u msecs\n", msecs));
00825   return result;
00826 }

Here is the call graph for this function:

err_t dhcp_select struct netif netif  )  [static]
 

Select a DHCP server offer out of all offers.

Simply select the first offer received.

Parameters:
netif the netif under DHCP control
Returns:
lwIP specific error (see error.h)

Definition at line 210 of file dhcp.c.

References DBG_STATE, DBG_TRACE, DEBUGF, DHCP_CLIENT_PORT, dhcp_create_request(), DHCP_DEBUG, dhcp_delete_request(), DHCP_FINE_TIMER_MSECS, dhcp_option(), DHCP_OPTION_BROADCAST, dhcp_option_byte(), dhcp_option_long(), DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, DHCP_OPTION_PARAMETER_REQUEST_LIST, DHCP_OPTION_REQUESTED_IP, DHCP_OPTION_ROUTER, DHCP_OPTION_SERVER_ID, dhcp_option_short(), DHCP_OPTION_SUBNET_MASK, dhcp_option_trailer(), DHCP_OPTIONS_LEN, DHCP_REQUEST, DHCP_REQUESTING, DHCP_SERVER_PORT, dhcp_set_state(), ERR_OK, err_t, IP_ADDR_ANY, IP_ADDR_BROADCAST, ntohl, pbuf_realloc(), u32_t, udp_bind(), udp_connect(), and udp_send().

Referenced by dhcp_handle_offer(), and dhcp_timeout().

00211 {
00212   struct dhcp *dhcp = netif->dhcp;
00213   err_t result;
00214   u32_t msecs;
00215   DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_select()\n"));
00216 
00217   /* create and initialize the DHCP message header */
00218   result = dhcp_create_request(netif);
00219   if (result == ERR_OK)
00220   {
00221     dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
00222     dhcp_option_byte(dhcp, DHCP_REQUEST);
00223 
00224     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00225     dhcp_option_short(dhcp, 576);
00226 
00227     /* MUST request the offered IP address */
00228     dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
00229     dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
00230 
00231     dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
00232     dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
00233 
00234     dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);
00235     dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
00236     dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
00237     dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
00238 
00239     dhcp_option_trailer(dhcp);
00240     /* shrink the pbuf to the actual content length */
00241     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00242 
00243     /* TODO: we really should bind to a specific local interface here
00244        but we cannot specify an unconfigured netif as it is addressless */
00245     udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00246     /* send broadcast to any DHCP server */
00247     udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
00248     udp_send(dhcp->pcb, dhcp->p_out);
00249     /* reconnect to any (or to server here?!) */
00250     udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
00251     dhcp_delete_request(netif);
00252     DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_select: REQUESTING\n"));
00253     dhcp_set_state(dhcp, DHCP_REQUESTING);
00254   } else {
00255     DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_select: could not allocate DHCP request\n"));
00256   }
00257   dhcp->tries++;
00258   msecs = dhcp->tries < 4 ? dhcp->tries * 1000 : 4 * 1000;
00259   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00260   DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_select(): set request timeout %u msecs\n", msecs));
00261   return result;
00262 }

Here is the call graph for this function:

void dhcp_set_state struct dhcp dhcp,
unsigned char  new_state
[static]
 

Definition at line 961 of file dhcp.c.

References dhcp::state, and dhcp::tries.

Referenced by dhcp_bind(), dhcp_check(), dhcp_discover(), dhcp_handle_nak(), dhcp_rebind(), dhcp_release(), dhcp_renew(), and dhcp_select().

00962 {
00963   if (new_state != dhcp->state)
00964   {
00965     dhcp->state = new_state;
00966     dhcp->tries = 0;
00967   }
00968 }

err_t dhcp_start struct netif netif  ) 
 

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.

Parameters:
netif The lwIP network interface
Returns:
lwIP error code
  • ERR_OK - No error
  • ERR_MEM - Out of memory

Definition at line 484 of file dhcp.c.

References DBG_STATE, DBG_TRACE, DEBUGF, DHCP_DEBUG, dhcp_discover(), dhcp_stop(), ERR_MEM, ERR_OK, err_t, netif::flags, LWIP_ASSERT, mem_free(), mem_malloc(), netif::name, NETIF_FLAG_DHCP, NULL, netif::num, and udp_new().

00485 {
00486   struct dhcp *dhcp = netif->dhcp;
00487   err_t result = ERR_OK;
00488 
00489   LWIP_ASSERT("netif != NULL", netif != NULL);
00490   DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_start(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num));
00491 
00492   if (dhcp == NULL) {
00493     DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
00494     dhcp = mem_malloc(sizeof(struct dhcp));
00495     if (dhcp == NULL) {
00496       DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
00497       netif->flags &= ~NETIF_FLAG_DHCP;
00498       return ERR_MEM;
00499     }
00500     /* clear data structure */
00501     memset(dhcp, 0, sizeof(struct dhcp));
00502     DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): allocated dhcp"));
00503     dhcp->pcb = udp_new();
00504     if (dhcp->pcb == NULL) {
00505       DEBUGF(DHCP_DEBUG  | DBG_TRACE, ("dhcp_start(): could not obtain pcb\n"));
00506       mem_free((void *)dhcp);
00507       dhcp = NULL;
00508       netif->flags &= ~NETIF_FLAG_DHCP;
00509       return ERR_MEM;
00510     }
00511     /* store this dhcp client in the netif */
00512     netif->dhcp = dhcp;
00513     DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): created new udp pcb\n"));
00514     DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
00515   } else {
00516     DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE | 3, ("dhcp_start(): restarting DHCP configuration\n"));
00517   }
00518   /* (re)start the DHCP negotiation */
00519   result = dhcp_discover(netif);
00520   if (result != ERR_OK) {
00521     /* free resources allocated above */
00522     dhcp_stop(netif);
00523   }
00524   return result;
00525 }

Here is the call graph for this function:

void dhcp_stop struct netif netif  ) 
 

Remove the DHCP client from the interface.

Parameters:
netif The network interface to stop DHCP on

Definition at line 930 of file dhcp.c.

References DBG_TRACE, DEBUGF, DHCP_DEBUG, dhcp_free_reply(), mem_free(), NULL, pbuf_free(), and udp_remove().

Referenced by dhcp_start().

00931 {
00932   struct dhcp *dhcp = netif->dhcp;
00933   DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_stop()\n"));
00934   /* netif is DHCP configured? */
00935   if (dhcp != NULL)
00936   {
00937     if (dhcp->pcb != NULL)
00938     {
00939       udp_remove(dhcp->pcb);
00940       dhcp->pcb = NULL;
00941     }
00942     if (dhcp->p != NULL)
00943     {
00944       pbuf_free(dhcp->p);
00945       dhcp->p = NULL;
00946     }
00947     /* free unfolded reply */
00948     dhcp_free_reply(dhcp);
00949     mem_free((void *)dhcp);
00950     netif->dhcp = NULL;
00951   }
00952 }

Here is the call graph for this function:

void dhcp_t1_timeout struct netif netif  )  [static]
 

The renewal period has timed out.

Parameters:
netif the netif under DHCP control

Definition at line 381 of file dhcp.c.

References DBG_STATE, DBG_TRACE, DEBUGF, DHCP_BOUND, DHCP_DEBUG, dhcp_renew(), DHCP_RENEWING, and DHCP_REQUESTING.

Referenced by dhcp_coarse_tmr().

00382 {
00383   struct dhcp *dhcp = netif->dhcp;
00384   DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_t1_timeout()\n"));
00385   if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
00386     /* just retry to renew */
00387     /* note that the rebind timer will eventually time-out if renew does not work */
00388     DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t1_timeout(): must renew\n"));
00389     dhcp_renew(netif);
00390   }
00391 }

Here is the call graph for this function:

void dhcp_t2_timeout struct netif netif  )  [static]
 

The rebind period has timed out.

Definition at line 397 of file dhcp.c.

References DBG_STATE, DBG_TRACE, DEBUGF, DHCP_BOUND, DHCP_DEBUG, dhcp_rebind(), DHCP_RENEWING, and DHCP_REQUESTING.

Referenced by dhcp_coarse_tmr().

00398 {
00399   struct dhcp *dhcp = netif->dhcp;
00400   DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t2_timeout()\n"));
00401   if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
00402     /* just retry to rebind */
00403     DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_t2_timeout(): must rebind\n"));
00404     dhcp_rebind(netif);
00405   }
00406 }

Here is the call graph for this function:

void dhcp_timeout struct netif netif  )  [static]
 

A DHCP negotiation transaction, or ARP request, has timed out.

The timer that was started with the DHCP or ARP request has timed out, indicating no response was received in time.

Parameters:
netif the netif under DHCP control

Definition at line 327 of file dhcp.c.

References DBG_STATE, DBG_TRACE, DEBUGF, DHCP_BACKING_OFF, dhcp_bind(), dhcp_check(), DHCP_CHECKING, DHCP_DEBUG, dhcp_discover(), dhcp_rebind(), DHCP_REBINDING, dhcp_release(), dhcp_renew(), DHCP_RENEWING, DHCP_REQUESTING, dhcp_select(), and DHCP_SELECTING.

Referenced by dhcp_fine_tmr().

00328 {
00329   struct dhcp *dhcp = netif->dhcp;
00330   DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_timeout()\n"));
00331   /* back-off period has passed, or server selection timed out */
00332   if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) {
00333     DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_timeout(): restarting discovery\n"));
00334     dhcp_discover(netif);
00335   /* receiving the requested lease timed out */
00336   } else if (dhcp->state == DHCP_REQUESTING) {
00337     DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n"));
00338     if (dhcp->tries <= 5) {
00339       dhcp_select(netif);
00340     } else {
00341       DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n"));
00342       dhcp_release(netif);
00343       dhcp_discover(netif);
00344     }
00345   /* received no ARP reply for the offered address (which is good) */
00346   } else if (dhcp->state == DHCP_CHECKING) {
00347     DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n"));
00348     if (dhcp->tries <= 1) {
00349       dhcp_check(netif);
00350     /* no ARP replies on the offered address, 
00351        looks like the IP address is indeed free */
00352     } else {
00353       /* bind the interface to the offered address */
00354       dhcp_bind(netif);
00355     }
00356   }
00357   /* did not get response to renew request? */
00358   else if (dhcp->state == DHCP_RENEWING) {
00359     DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_timeout(): RENEWING, DHCP request timed out\n"));
00360     /* just retry renewal */ 
00361     /* note that the rebind timer will eventually time-out if renew does not work */
00362     dhcp_renew(netif);
00363   /* did not get response to rebind request? */
00364   } else if (dhcp->state == DHCP_REBINDING) {
00365     DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_timeout(): REBINDING, DHCP request timed out\n"));
00366     if (dhcp->tries <= 8) {
00367       dhcp_rebind(netif);
00368     } else {
00369       DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_timeout(): RELEASING, DISCOVERING\n"));
00370       dhcp_release(netif);
00371       dhcp_discover(netif);
00372     }
00373   }
00374 }

Here is the call graph for this function:

err_t dhcp_unfold_reply struct dhcp dhcp  )  [static]
 

Extract the DHCP message and the DHCP options.

Extract the DHCP message and the DHCP options, each into a contiguous piece of memory. As a DHCP message is variable sized by its options, and also allows overriding some fields for options, the easy approach is to first unfold the options into a conitguous piece of memory, and use that further on.

Definition at line 1015 of file dhcp.c.

References DBG_TRACE, DEBUGF, DHCP_DEBUG, dhcp_free_reply(), DHCP_OPTIONS_LEN, ERR_MEM, ERR_OK, err_t, mem_free(), mem_malloc(), dhcp::msg_in, NULL, dhcp::options_in, dhcp::options_in_len, dhcp::p, pbuf::tot_len, u16_t, and u8_t.

Referenced by dhcp_recv().

01016 {
01017   struct pbuf *p = dhcp->p;
01018   u8_t *ptr;
01019   u16_t i;
01020   u16_t j = 0;
01021   /* free any left-overs from previous unfolds */
01022   dhcp_free_reply(dhcp);
01023   dhcp->msg_in = NULL;
01024   dhcp->options_in = NULL;
01025   /* options present? */
01026   if (dhcp->p->tot_len > (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN))
01027   {
01028     dhcp->options_in_len = dhcp->p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
01029     dhcp->options_in = mem_malloc(dhcp->options_in_len);
01030     if (dhcp->options_in == NULL)
01031     {
01032       DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_unfold_reply(): could not allocate dhcp->options\n")); 
01033       return ERR_MEM;
01034     }
01035   }
01036   dhcp->msg_in = mem_malloc(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
01037   if (dhcp->msg_in == NULL)
01038   {
01039     DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_unfold_reply(): could not allocate dhcp->msg_in\n")); 
01040     mem_free((void *)dhcp->options_in);
01041     dhcp->options_in = NULL;
01042     return ERR_MEM;
01043   }
01044 
01045   ptr = (u8_t *)dhcp->msg_in;
01046   /* proceed through struct dhcp_msg */
01047   for (i = 0; i < sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN; i++)
01048   {
01049     *ptr++ = ((u8_t *)p->payload)[j++];
01050     /* reached end of pbuf? */
01051     if (j == p->len)
01052     {
01053       /* proceed to next pbuf in chain */
01054       p = p->next;
01055       j = 0;
01056     }
01057   }
01058   DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %u bytes into dhcp->msg_in[]\n", i)); 
01059   if (dhcp->options_in != NULL) {
01060     ptr = (u8_t *)dhcp->options_in;
01061     /* proceed through options */
01062     for (i = 0; i < dhcp->options_in_len; i++) {
01063       *ptr++ = ((u8_t *)p->payload)[j++];
01064       /* reached end of pbuf? */
01065       if (j == p->len) {
01066         /* proceed to next pbuf in chain */
01067         p = p->next;
01068         j = 0;
01069       }
01070     }
01071     DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %u bytes to dhcp->options_in[]\n", i)); 
01072   }
01073   return ERR_OK;
01074 }

Here is the call graph for this function:


Variable Documentation

u32_t xid = 0xABCD0000 [static]
 

global transaction identifier, must be unique for each DHCP request.

Definition at line 91 of file dhcp.c.

Referenced by dhcp_create_request().


Generated on Wed Jan 14 12:59:03 2004 for RTL-lwIP-0.4 by doxygen 1.3.4