/[lwip]/lwip/src/core/dhcp.c
ViewVC logotype

Diff of /lwip/src/core/dhcp.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.11.2.2 by likewise, Mon Feb 10 20:16:11 2003 UTC revision 1.11.2.3 by likewise, Mon Feb 10 22:42:59 2003 UTC
# Line 59  Line 59 
59   *   *
60   * How to boot the DHCP client   * How to boot the DHCP client
61   *   *
62   * First, call dhcp_init() to initialize the DHCP client.   * struct dhcp *client = dhcp_start(struct netif *netif);
  *  
  * Then, use  
  * struct dhcp_state *client = dhcp_start(struct netif *netif)  
63   * starts a DHCP client instance which configures the interface by   * starts a DHCP client instance which configures the interface by
64   * obtaining an IP address lease and maintaining it.   * obtaining an IP address lease and maintaining it.
65   *   *
66   * Use dhcp_release(client) to end the lease and use dhcp_stop(client)   * Use dhcp_release(netif) to end the lease and use dhcp_stop(netif)
67   * to remove the DHCP client.   * to remove the DHCP client.
68   *   *
69   */   */
# Line 81  Line 78 
78  #include "lwipopts.h"  #include "lwipopts.h"
79  #include "lwip/dhcp.h"  #include "lwip/dhcp.h"
80    
 /** find the active DHCP attached to the given network interface */  
 struct dhcp_state *dhcp_find_client(struct netif *netif);  
   
81  /** transaction identifier, unique over all DHCP requests */  /** transaction identifier, unique over all DHCP requests */
82  static u32_t xid = 0xABCD0000;  static u32_t xid = 0xABCD0000;
83    
84  /** DHCP client state machine functions */  /** DHCP client state machine functions */
85  static void dhcp_handle_ack(struct dhcp_state *state);  static void dhcp_handle_ack(struct dhcp *dhcp);
86  static void dhcp_handle_nak(struct dhcp_state *state);  static void dhcp_handle_nak(struct dhcp *dhcp);
87  static void dhcp_handle_offer(struct dhcp_state *state);  static void dhcp_handle_offer(struct dhcp *dhcp);
88  static err_t dhcp_discover(struct dhcp_state *state);  
89  static err_t dhcp_select(struct dhcp_state *state);  static err_t dhcp_discover(struct netif *netif);
90  static void dhcp_check(struct dhcp_state *state);  static err_t dhcp_select(struct netif *netif);
91  static err_t dhcp_decline(struct dhcp_state *state);  static void dhcp_check(struct netif *netif);
92  static void dhcp_bind(struct dhcp_state *state);  static void dhcp_bind(struct netif *netif);
93  static err_t dhcp_rebind(struct dhcp_state *state);  static err_t dhcp_decline(struct netif *netif);
94  static err_t dhcp_release(struct dhcp_state *state);  static err_t dhcp_rebind(struct netif *netif);
95  static void dhcp_set_state(struct dhcp_state *state, unsigned char new_state);  static err_t dhcp_release(struct netif *netif);
96    static void dhcp_set_state(struct dhcp *dhcp, unsigned char new_state);
97    
98  /** receive, unfold, parse and free incoming messages */  /** receive, unfold, parse and free incoming messages */
99  static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);  static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
100  static err_t dhcp_unfold_reply(struct dhcp_state *state);  static err_t dhcp_unfold_reply(struct dhcp *dhcp);
101  static u8_t *dhcp_get_option_ptr(struct dhcp_state *state, u8_t option_type);  static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type);
102  static u8_t dhcp_get_option_byte(u8_t *ptr);  static u8_t dhcp_get_option_byte(u8_t *ptr);
103  static u16_t dhcp_get_option_short(u8_t *ptr);  static u16_t dhcp_get_option_short(u8_t *ptr);
104  static u32_t dhcp_get_option_long(u8_t *ptr);  static u32_t dhcp_get_option_long(u8_t *ptr);
105  static void dhcp_free_reply(struct dhcp_state *state);  static void dhcp_free_reply(struct dhcp *dhcp);
106    
107  /** set the DHCP timers */  /** set the DHCP timers */
108  static void dhcp_timeout(struct dhcp_state *state);  static void dhcp_timeout(struct netif *netif);
109  static void dhcp_t1_timeout(struct dhcp_state *state);  static void dhcp_t1_timeout(struct dhcp *dhcp);
110  static void dhcp_t2_timeout(struct dhcp_state *state);  static void dhcp_t2_timeout(struct dhcp *dhcp);
   
 #if DHCP_DOES_ARP_CHECK  
 /** called by ARP to notify us of ARP replies */  
 void dhcp_arp_reply(struct ip_addr *addr);  
 #endif  
111    
112  /** build outgoing messages */  /** build outgoing messages */
113  static err_t dhcp_create_request(struct dhcp_state *state);  static err_t dhcp_create_request(struct dhcp *dhcp);
114  static void dhcp_delete_request(struct dhcp_state *state);  static void dhcp_delete_request(struct dhcp *dhcp);
115  static void dhcp_option(struct dhcp_state *state, u8_t option_type, u8_t option_len);  static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len);
116  static void dhcp_option_byte(struct dhcp_state *state, u8_t value);  static void dhcp_option_byte(struct dhcp *dhcp, u8_t value);
117  static void dhcp_option_short(struct dhcp_state *state, u16_t value);  static void dhcp_option_short(struct dhcp *dhcp, u16_t value);
118  static void dhcp_option_long(struct dhcp_state *state, u32_t value);  static void dhcp_option_long(struct dhcp *dhcp, u32_t value);
119  static void dhcp_option_trailer(struct dhcp_state *state);  static void dhcp_option_trailer(struct dhcp *dhcp);
120    
121  /**  /**
122   * Back-off the DHCP client (because of a received NAK response).   * Back-off the DHCP client (because of a received NAK response).
# Line 139  static void dhcp_option_trailer(struct d Line 129  static void dhcp_option_trailer(struct d
129   *   *
130   * @param state pointer to DHCP state structure   * @param state pointer to DHCP state structure
131   */   */
132  static void dhcp_handle_nak(struct dhcp_state *state) {  static void dhcp_handle_nak(struct dhcp *dhcp) {
133      struct dhcp *dhcp = netif->dhcp;
134    u16_t msecs = 10 * 1000;    u16_t msecs = 10 * 1000;
135    DEBUGF(DHCP_DEBUG, ("dhcp_handle_nak()"));    DEBUGF(DHCP_DEBUG, ("dhcp_handle_nak()"));
136    state->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;    dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
137    DEBUGF(DHCP_DEBUG, ("dhcp_handle_nak(): set request timeout %u msecs", msecs));    DEBUGF(DHCP_DEBUG, ("dhcp_handle_nak(): set request timeout %u msecs", msecs));
138    dhcp_set_state(state, DHCP_BACKING_OFF);    dhcp_set_state(dhcp, DHCP_BACKING_OFF);
139  }  }
140    
141  /**  /**
# Line 154  static void dhcp_handle_nak(struct dhcp_ Line 145  static void dhcp_handle_nak(struct dhcp_
145   * entering CHECKING state. If no ARP reply is received within a small   * entering CHECKING state. If no ARP reply is received within a small
146   * interval, the address is assumed to be free for use by us.   * interval, the address is assumed to be free for use by us.
147   */   */
148  static void dhcp_check(struct dhcp_state *state)  static void dhcp_check(struct netif *netif)
149  {  {
150    struct dhcp_state *state;;    struct dhcp *dhcp = netif->dhcp;
151    struct pbuf *p;    struct pbuf *p;
152    err_t result;    err_t result;
153    u16_t msecs;    u16_t msecs;
154    DEBUGF(DHCP_DEBUG, ("dhcp_check()"));    DEBUGF(DHCP_DEBUG, ("dhcp_check()"));
155    /* create an ARP query for the offered IP address, expecting that no host    /* create an ARP query for the offered IP address, expecting that no host
156       responds, as the IP address should not be in use. */       responds, as the IP address should not be in use. */
157    p = etharp_query(state->netif, &state->offered_ip_addr, NULL);    p = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
158    if(p != NULL)    if (p != NULL)
159    {    {
160      DEBUGF(DHCP_DEBUG, ("dhcp_check(): sending ARP request len %u", p->tot_len));      DEBUGF(DHCP_DEBUG, ("dhcp_check(): sending ARP request len %u", p->tot_len));
161      result = state->netif->linkoutput(state->netif, p);      result = dhcp->netif->linkoutput(netif, p);
162      pbuf_free(p);      pbuf_free(p);
163      p = NULL;      p = NULL;
164    }    }
165    state->tries++;    dhcp->tries++;
166    msecs = 500;    msecs = 500;
167    state->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;    dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
168    DEBUGF(DHCP_DEBUG, ("dhcp_check(): set request timeout %u msecs", msecs));    DEBUGF(DHCP_DEBUG, ("dhcp_check(): set request timeout %u msecs", msecs));
169    dhcp_set_state(state, DHCP_CHECKING);    dhcp_set_state(dhcp, DHCP_CHECKING);
170  }  }
171    
172  /**  /**
# Line 183  static void dhcp_check(struct dhcp_state Line 174  static void dhcp_check(struct dhcp_state
174   *   *
175   * @param state pointer to DHCP state structure   * @param state pointer to DHCP state structure
176   */   */
177  static void dhcp_handle_offer(struct dhcp_state *state)  static void dhcp_handle_offer(struct dhcp *dhcp)
178  {  {
179    /* obtain the server address */    /* obtain the server address */
180    u8_t *option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_SERVER_ID);    u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID);
181    if (option_ptr != NULL)    if (option_ptr != NULL)
182    {    {
183      state->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));      dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
184      DEBUGF(DHCP_DEBUG, ("dhcp_handle_offer(): server 0x%08lx", state->server_ip_addr.addr));      DEBUGF(DHCP_DEBUG, ("dhcp_handle_offer(): server 0x%08lx", dhcp->server_ip_addr.addr));
185      /* remember offered address */      /* remember offered address */
186      ip_addr_set(&state->offered_ip_addr, (struct ip_addr *)&state->msg_in->yiaddr);      ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr);
187      DEBUGF(DHCP_DEBUG, ("dhcp_handle_offer(): offer for 0x%08lx", state->offered_ip_addr.addr));      DEBUGF(DHCP_DEBUG, ("dhcp_handle_offer(): offer for 0x%08lx", dhcp->offered_ip_addr.addr));
188      dhcp_select(state);      dhcp_select(dhcp);
189    }    }
190    else    else
191    {    {
192      //dhcp_start(restart);      /* dhcp_start(restart); */
193    }    }
194  }  }
195    
# Line 207  static void dhcp_handle_offer(struct dhc Line 198  static void dhcp_handle_offer(struct dhc
198   *   *
199   * Simply select the first offer received.   * Simply select the first offer received.
200   *   *
201   * @param state pointer to DHCP state structure   * @param dhcp pointer to DHCP state structure
202   * @return lwIP specific error (see error.h)   * @return lwIP specific error (see error.h)
203   */   */
204  static err_t dhcp_select(struct dhcp_state *state)  static err_t dhcp_select(struct dhcp *dhcp)
205  {  {
206    err_t result;    err_t result;
207    u32_t msecs;    u32_t msecs;
208    DEBUGF(DHCP_DEBUG, ("dhcp_select()"));    DEBUGF(DHCP_DEBUG, ("dhcp_select()"));
209    
210    // create and initialize the DHCP message header    /* create and initialize the DHCP message header */
211    result = dhcp_create_request(state);    result = dhcp_create_request(dhcp);
212    if (result == ERR_OK)    if (result == ERR_OK)
213    {    {
214      dhcp_option(state, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);      dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
215      dhcp_option_byte(state, DHCP_REQUEST);      dhcp_option_byte(dhcp, DHCP_REQUEST);
216    
217      dhcp_option(state, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);      dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
218      dhcp_option_short(state, 576);      dhcp_option_short(dhcp, 576);
219    
220      /* MUST request the offered IP address */      /* MUST request the offered IP address */
221      dhcp_option(state, DHCP_OPTION_REQUESTED_IP, 4);      dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
222      dhcp_option_long(state, ntohl(state->offered_ip_addr.addr));      dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
   
     dhcp_option(state, DHCP_OPTION_SERVER_ID, 4);  
     dhcp_option_long(state, ntohl(state->server_ip_addr.addr));  
   
      dhcp_option(state, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);  
     dhcp_option_byte(state, DHCP_OPTION_SUBNET_MASK);  
     dhcp_option_byte(state, DHCP_OPTION_ROUTER);  
     dhcp_option_byte(state, DHCP_OPTION_BROADCAST);  
223    
224      dhcp_option_trailer(state);      dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
225        dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
226    
227      pbuf_realloc(state->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + state->options_out_len);      dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);
228        dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
229        dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
230        dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
231    
232        dhcp_option_trailer(dhcp);
233        /* shrink the pbuf to the actual content length */
234        pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
235    
236      /* TODO: we really should bind to a specific local interface here      /* TODO: we really should bind to a specific local interface here
237         but we cannot specify an unconfigured netif as it is addressless */         but we cannot specify an unconfigured netif as it is addressless */
238      udp_bind(state->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);      udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
239      /* listen to broadcast traffic from a DHCP server */      /* send broadcast to any DHCP server */
240      udp_connect(state->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);      udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
241      udp_send(state->pcb, state->p_out);      udp_send(dhcp->pcb, dhcp->p_out);
242      // reconnect to any (or to server here?!)      /* reconnect to any (or to server here?!) */
243      udp_connect(state->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);      udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
244      dhcp_delete_request(state);      dhcp_delete_request(dhcp);
245    }    }
246    state->tries++;    dhcp->tries++;
247    msecs = state->tries < 4 ? state->tries * 1000 : 4 * 1000;    msecs = dhcp->tries < 4 ? dhcp->tries * 1000 : 4 * 1000;
248    state->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;    dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
249     DEBUGF(DHCP_DEBUG, ("dhcp_select(): set request timeout %u msecs", msecs));    DEBUGF(DHCP_DEBUG, ("dhcp_select(): set request timeout %u msecs", msecs));
250    dhcp_set_state(state, DHCP_REQUESTING);    dhcp_set_state(dhcp, DHCP_REQUESTING);
251    return result;    return result;
252  }  }
253    
254  /**  /**
255   * The DHCP timer that checks for lease renewal/rebind timeouts.   * The DHCP timer that checks for lease renewal/rebind timeouts.
256   *   *
  * @param state pointer to DHCP state structure  
257   */   */
258  void dhcp_coarse_tmr()  void dhcp_coarse_tmr()
259  {  {
260    struct dhcp_state *list_state = client_list;    struct netif *netif = netif_list;
261     DEBUGF(DHCP_DEBUG, ("dhcp_coarse_tmr():"));    DEBUGF(DHCP_DEBUG, ("dhcp_coarse_tmr():"));
262    // loop through clients    /* iterate through all network interfaces */
263    while (list_state != NULL)    while (netif != NULL) {
264    {      /* only act on DHCP configured interfaces */
265      // timer is active (non zero), and triggers (zeroes) now      if (netif->dhcp != NULL) {
266      if (list_state->t2_timeout-- == 1)        /* timer is active (non zero), and triggers (zeroes) now? */
267      {        if (netif->dhcp->t2_timeout-- == 1) {
268         DEBUGF(DHCP_DEBUG, ("dhcp_coarse_tmr(): t2 timeout"));          DEBUGF(DHCP_DEBUG, ("dhcp_coarse_tmr(): t2 timeout"));
269        // this clients' rebind timeout triggered          /* this clients' rebind timeout triggered */
270        dhcp_t2_timeout(list_state);          dhcp_t2_timeout(netif);
271      }        /* timer is active (non zero), and triggers (zeroes) now */
272      // timer is active (non zero), and triggers (zeroes) now        } else if (netif->dhcp->t1_timeout-- == 1) {
273      else if (list_state->t1_timeout-- == 1)          DEBUGF(DHCP_DEBUG, ("dhcp_coarse_tmr(): t1 timeout"));
274      {          /* this clients' renewal timeout triggered */
275         DEBUGF(DHCP_DEBUG, ("dhcp_coarse_tmr(): t1 timeout"));          dhcp_t1_timeout(netif);
276        // this clients' renewal timeout triggered        }
       dhcp_t1_timeout(list_state);  
277      }      }
278      // proceed to next timer      /* proceed to next netif */
279      list_state = list_state->next;      netif = netif->next;
280    }    }
281  }  }
282    
283  /**  /**
284   * The DHCP timer that handles DHCP negotiotion transaction timeouts.   * The DHCP timer that handles DHCP negotiation transaction timeouts.
285   *   *
286   */   */
287  void dhcp_fine_tmr()  void dhcp_fine_tmr()
288  {  {
289    struct dhcp_state *list_state = client_list;    struct netif *netif = netif_list;
 //   DEBUGF(DHCP_DEBUG, ("dhcp_fine_tmr():"));  
290    /* loop through clients */    /* loop through clients */
291    while (list_state != NULL)    while (netif != NULL) {
292    {      /* only act on DHCP configured interfaces */
293      /* timer is active (non zero), and triggers (zeroes) now */      if (netif->dhcp != NULL) {
294      if (list_state->request_timeout-- == 1)        /* timer is active (non zero), and triggers (zeroes) now */
295      {        if (netif->dhcp->request_timeout-- == 1) {
296         DEBUGF(DHCP_DEBUG, ("dhcp_fine_tmr(): request timeout"));          DEBUGF(DHCP_DEBUG, ("dhcp_fine_tmr(): request timeout"));
297        /* this clients' request timeout triggered */          /* this clients' request timeout triggered */
298        dhcp_timeout(list_state);          dhcp_timeout(netif);
299          }
300      }      }
301      /* proceed to next client */      /* proceed to next network interface */
302      list_state = list_state->next;      netif = netif->next;
303    }    }
304  }  }
305    
# Line 320  void dhcp_fine_tmr() Line 309  void dhcp_fine_tmr()
309   * The timer that was started with the DHCP or ARP request has   * The timer that was started with the DHCP or ARP request has
310   * timed out, indicating no response was received.   * timed out, indicating no response was received.
311   *   *
312   * @param state pointer to DHCP state structure   * @param dhcp pointer to DHCP state structure
313   *   *
314   */   */
315  static void dhcp_timeout(struct dhcp_state *state)  static void dhcp_timeout(struct netif *netif)
316  {  {
317    DEBUGF(DHCP_DEBUG, ("dhcp_timeout()"));    DEBUGF(DHCP_DEBUG, ("dhcp_timeout()"));
318    /* back-off period has passed, or server selection timed out */    /* back-off period has passed, or server selection timed out */
319    if ((state->state == DHCP_BACKING_OFF) || (state->state == DHCP_SELECTING))    if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) {
   {  
320      DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): restarting discovery"));      DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): restarting discovery"));
321      dhcp_discover(state);      dhcp_discover(dhcp);
   }  
322    /* receiving the requested lease timed out */    /* receiving the requested lease timed out */
323    else if (state->state == DHCP_REQUESTING)    } else if (dhcp->state == DHCP_REQUESTING) {
   {  
324      DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REQUESTING, DHCP request timed out"));      DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REQUESTING, DHCP request timed out"));
325      if (state->tries <= 5)      if (dhcp->tries <= 5) {
326      {        dhcp_select(dhcp);
327        dhcp_select(state);      } else {
     }  
     else  
     {  
328        DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REQUESTING, releasing, restarting"));        DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REQUESTING, releasing, restarting"));
329        dhcp_release(state);        dhcp_release(dhcp);
330        dhcp_discover(state);        dhcp_discover(dhcp);
331      }      }
   }  
332    /* received no ARP reply for the offered address (which is good) */    /* received no ARP reply for the offered address (which is good) */
333    else if (state->state == DHCP_CHECKING)    } else if (dhcp->state == DHCP_CHECKING) {
   {  
334      DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): CHECKING, ARP request timed out"));      DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): CHECKING, ARP request timed out"));
335      if (state->tries <= 1)      if (dhcp->tries <= 1) {
336       {        dhcp_check(netif);
       dhcp_check(state);  
     }  
337      /* no ARP replies on the offered address,      /* no ARP replies on the offered address,
338         looks like the IP address is indeed free */         looks like the IP address is indeed free */
339      else      } else {
     {  
340        /* bind the interface to the offered address */        /* bind the interface to the offered address */
341        dhcp_bind(state);        dhcp_bind(netif);
342      }      }
343    }    }
344    /* did not get response to renew request? */    /* did not get response to renew request? */
345    else if (state->state == DHCP_RENEWING)    else if (dhcp->state == DHCP_RENEWING) {
   {  
346      DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): RENEWING, DHCP request timed out"));      DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): RENEWING, DHCP request timed out"));
347      /* just retry renewal */      /* just retry renewal */
348      /* note that the rebind timer will eventually time-out if renew does not work */      /* note that the rebind timer will eventually time-out if renew does not work */
349      dhcp_renew(state);      dhcp_renew(dhcp);
   }  
350    /* did not get response to rebind request? */    /* did not get response to rebind request? */
351    else if (state->state == DHCP_REBINDING)    } else if (dhcp->state == DHCP_REBINDING) {
   {  
352      DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REBINDING, DHCP request timed out"));      DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REBINDING, DHCP request timed out"));
353      if (state->tries <= 8)      if (dhcp->tries <= 8) {
354      {        dhcp_rebind(dhcp);
355        dhcp_rebind(state);      } else {
     }  
     else  
     {  
356        DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): RELEASING, DISCOVERING"));        DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): RELEASING, DISCOVERING"));
357        dhcp_release(state);        dhcp_release(dhcp);
358        dhcp_discover(state);        dhcp_discover(dhcp);
359      }      }
360    }    }
361  }  }
# Line 391  static void dhcp_timeout(struct dhcp_sta Line 363  static void dhcp_timeout(struct dhcp_sta
363  /**  /**
364   * The renewal period has timed out.   * The renewal period has timed out.
365   *   *
366   * @param state pointer to DHCP state structure   * @param dhcp pointer to DHCP state structure
367   */   */
368  static void dhcp_t1_timeout(struct dhcp_state *state)  static void dhcp_t1_timeout(struct netif *netif)
369  {  {
370      struct dhcp *dhcp = netif->dhcp;
371    DEBUGF(DHCP_DEBUG, ("dhcp_t1_timeout()"));    DEBUGF(DHCP_DEBUG, ("dhcp_t1_timeout()"));
372    if ((state->state == DHCP_REQUESTING) || (state->state == DHCP_BOUND) || (state->state == DHCP_RENEWING))    if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
   {  
373      /* just retry to renew */      /* just retry to renew */
374      /* note that the rebind timer will eventually time-out if renew does not work */      /* note that the rebind timer will eventually time-out if renew does not work */
375      DEBUGF(DHCP_DEBUG, ("dhcp_t1_timeout(): must renew"));      DEBUGF(DHCP_DEBUG, ("dhcp_t1_timeout(): must renew"));
376      dhcp_renew(state);      dhcp_renew(netif);
377    }    }
378  }  }
379    
# Line 409  static void dhcp_t1_timeout(struct dhcp_ Line 381  static void dhcp_t1_timeout(struct dhcp_
381   * The rebind period has timed out.   * The rebind period has timed out.
382   *   *
383   */   */
384  static void dhcp_t2_timeout(struct dhcp_state *state)  static void dhcp_t2_timeout(struct netif *netif)
385  {  {
386      struct dhcp *dhcp = netif->dhcp;
387    DEBUGF(DHCP_DEBUG, ("dhcp_t2_timeout()"));    DEBUGF(DHCP_DEBUG, ("dhcp_t2_timeout()"));
388    if ((state->state == DHCP_REQUESTING) || (state->state == DHCP_BOUND) || (state->state == DHCP_RENEWING))    if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
   {  
389      /* just retry to rebind */      /* just retry to rebind */
390      DEBUGF(DHCP_DEBUG, ("dhcp_t2_timeout(): must rebind"));      DEBUGF(DHCP_DEBUG, ("dhcp_t2_timeout(): must rebind"));
391      dhcp_rebind(state);      dhcp_rebind(netif);
392    }    }
393  }  }
394    
395  /**  /**
396   * Extract options from the server ACK message.   * Extract options from the server ACK message.
397   *   *
398   * @param state pointer to DHCP state structure   * @param dhcp pointer to DHCP state structure
399   */   */
400  static void dhcp_handle_ack(struct dhcp_state *state)  static void dhcp_handle_ack(struct dhcp *dhcp)
401  {  {
402    u8_t *option_ptr;    u8_t *option_ptr;
403    /* clear options we might not get from the ACK */    /* clear options we might not get from the ACK */
404    state->offered_sn_mask.addr = 0;    dhcp->offered_sn_mask.addr = 0;
405    state->offered_gw_addr.addr = 0;    dhcp->offered_gw_addr.addr = 0;
406    state->offered_bc_addr.addr = 0;    dhcp->offered_bc_addr.addr = 0;
407    
408    /* lease time given? */    /* lease time given? */
409    option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_LEASE_TIME);    option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_LEASE_TIME);
410    if (option_ptr != NULL)    if (option_ptr != NULL) {
   {  
411      /* remember offered lease time */      /* remember offered lease time */
412      state->offered_t0_lease = dhcp_get_option_long(option_ptr + 2);      dhcp->offered_t0_lease = dhcp_get_option_long(option_ptr + 2);
     /* calculate safe periods for renewal and rebinding */  
     state->offered_t1_renew = state->offered_t0_lease / 2;  
     state->offered_t2_rebind = state->offered_t0_lease;  
413    }    }
414    /* renewal period given? */    /* renewal period given? */
415    option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_T1);    option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T1);
416    if (option_ptr != NULL)    if (option_ptr != NULL) {
   {  
417      /* remember given renewal period */      /* remember given renewal period */
418      state->offered_t1_renew = dhcp_get_option_long(option_ptr + 2);      dhcp->offered_t1_renew = dhcp_get_option_long(option_ptr + 2);
419      } else {
420        /* calculate safe periods for renewal */
421        dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2;
422    }    }
423    
424    /* renewal period given? */    /* renewal period given? */
425    option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_T2);    option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T2);
426    if (option_ptr != NULL)    if (option_ptr != NULL) {
   {  
427      /* remember given rebind period */      /* remember given rebind period */
428      state->offered_t2_rebind = dhcp_get_option_long(option_ptr + 2);      dhcp->offered_t2_rebind = dhcp_get_option_long(option_ptr + 2);
429      } else {
430        /* calculate safe periods for rebinding */
431        dhcp->offered_t2_rebind = dhcp->offered_t0_lease;
432    }    }
433    
434    /* (y)our internet address */    /* (y)our internet address */
435    ip_addr_set(&state->offered_ip_addr, &state->msg_in->yiaddr);    ip_addr_set(&dhcp->offered_ip_addr, &dhcp->msg_in->yiaddr);
436    
437    /* subnet mask */    /* subnet mask */
438    option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_SUBNET_MASK);    option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SUBNET_MASK);
439    /* subnet mask given? */    /* subnet mask given? */
440    if (option_ptr != NULL)    if (option_ptr != NULL) {
441    {      dhcp->offered_sn_mask.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
     state->offered_sn_mask.addr = htonl(dhcp_get_option_long(&option_ptr[2]));  
442    }    }
443    
444    /* gateway router */    /* gateway router */
445    option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_ROUTER);    option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_ROUTER);
446    if (option_ptr != NULL)    if (option_ptr != NULL) {
447    {      dhcp->offered_gw_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
     state->offered_gw_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));  
448    }    }
449    
450    /* broadcast address */    /* broadcast address */
451    option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_BROADCAST);    option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_BROADCAST);
452    if (option_ptr != NULL)    if (option_ptr != NULL) {
453    {      dhcp->offered_bc_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
     state->offered_bc_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));  
454    }    }
455  }  }
456    
   
 /**  
  * Initialize DHCP.  
  *  
  * Must be called prior to any other dhcp_*() function.  
  *  
  */  
 void dhcp_init(void)  
 {  
   DEBUGF(DHCP_DEBUG, ("dhcp_init()"));  
   /* this would be the proper way to stop all dhcp clients */  
   /* but we need lwIP to be running at this point */  
   /* while(client_list) dhcp_stop(client_list); */  
   client_list = NULL;  
 }  
   
457  /**  /**
458   * Start DHCP negotiation for a network interface.   * Start DHCP negotiation for a network interface.
459   *   *
# Line 513  void dhcp_init(void) Line 468  void dhcp_init(void)
468   * (due to unavailable memory or network resources).   * (due to unavailable memory or network resources).
469   *   *
470   */   */
471  struct dhcp_state *dhcp_start(struct netif *netif)  struct dhcp *dhcp_start(struct netif *netif)
472  {  {
473    struct dhcp_state *state = NULL;    struct dhcp *dhcp = netif->dhcp;
   struct dhcp_state *list_state = client_list;  
474    err_t result = ERR_OK;    err_t result = ERR_OK;
475    
476    DEBUGF(DHCP_DEBUG, ("dhcp_start()"));    DEBUGF(DHCP_DEBUG, ("dhcp_start(netif=%c%c%u)", netif->, netif->, netif->num));
477    
478    /* find the DHCP client attached to the given interface */    if (dhcp == NULL) {
479    state = dhcp_find_client(netif);      DEBUGF(DHCP_DEBUG, ("dhcp_start(): starting new DHCP client"));
480    DEBUGF(DHCP_DEBUG, ("dhcp_start(): finished parsing through list"));      dhcp = mem_malloc(sizeof(struct dhcp));
481    /* a DHCP client already attached to this interface? */      if (dhcp == NULL) {
482    if (state != NULL)        DEBUGF(DHCP_DEBUG, ("dhcp_start(): could not allocate dhcp"));
483    {        netif->flags &= ~NETIF_FLAG_DHCP;
484      DEBUGF(DHCP_DEBUG, ("dhcp_start(): already active on interface"));        return ERR_MEM;
     /* just restart the DHCP negotiation */  
     result = dhcp_discover(state);  
     if (result == ERR_OK)  
     {  
       return state;  
485      }      }
486      else      /* clear data structure */
487      {      memset(dhcp, 0, sizeof(struct dhcp));
488        dhcp_stop(state);      DEBUGF(DHCP_DEBUG, ("dhcp_start(): allocated dhcp"));
489        return NULL;      dhcp->pcb = udp_new();
490        if (dhcp->pcb == NULL) {
491          DEBUGF(DHCP_DEBUG, ("dhcp_start(): could not obtain pcb"));
492          mem_free((void *)dhcp);
493          dhcp = NULL;
494          netif->flags &= ~NETIF_FLAG_DHCP;
495          return ERR_MEM;
496      }      }
497        /* store this dhcp client in the netif */
498        netif->dhcp = dhcp;
499        DEBUGF(DHCP_DEBUG, ("dhcp_start(): created new udp pcb"));
500        DEBUGF(DHCP_DEBUG, ("dhcp_start(): starting DHCP configuration"));
501      } else {
502        DEBUGF(DHCP_DEBUG, ("dhcp_start(): restarting DHCP configuration"));
503      }
504      /* (re)start the DHCP negotiation */
505      result = dhcp_discover(netif);
506      if (result != ERR_OK) {
507        /* free resources allocated above */
508        dhcp_stop(netif);
509    }    }
510      return result;
   DEBUGF(DHCP_DEBUG, ("dhcp_start(): starting new DHCP client"));  
   state = mem_malloc(sizeof(struct dhcp_state));  
   if (state == NULL)  
   {  
     DEBUGF(DHCP_DEBUG, ("dhcp_start(): could not allocate dhcp_state"));  
     return NULL;  
   }  
   memset(state, 0, sizeof(struct dhcp_state));  
   
   DEBUGF(DHCP_DEBUG, ("dhcp_start(): allocated dhcp_state"));  
   state->pcb = udp_new();  
   if (state->pcb == NULL) {  
     DEBUGF(DHCP_DEBUG, ("dhcp_start(): could not obtain pcb"));  
     mem_free((void *)state);  
     state = NULL;  
     return NULL;  
   }  
   DEBUGF(DHCP_DEBUG, ("dhcp_start(): created new udp pcb"));  
   state->netif = netif;  
   /* enqueue in list of clients */  
   /* we are last in list */  
   state->next = NULL;  
   /* empty list? */  
   if (client_list == NULL)  
   {  
     /* single item at head of list */  
     client_list = state;  
   }  
   else  
   {  
     /* proceed to the last DHCP client state */  
     while (list_state->next != NULL) list_state = list_state->next;  
     list_state->next = state;  
   }  
   dhcp_discover(state);  
   return state;  
511  }  }
512    
513  /**  /**
# Line 591  struct dhcp_state *dhcp_start(struct net Line 522  struct dhcp_state *dhcp_start(struct net
522   */   */
523  void dhcp_inform(struct netif *netif)  void dhcp_inform(struct netif *netif)
524  {  {
525    struct dhcp_state *state = NULL;    struct dhcp *dhcp;
526    err_t result = ERR_OK;    err_t result = ERR_OK;
527    state = mem_malloc(sizeof(struct dhcp_state));    dhcp = mem_malloc(sizeof(struct dhcp));
528    if (state == NULL)    if (dhcp == NULL) {
529    {      DEBUGF(DHCP_DEBUG, ("dhcp_inform(): could not allocate dhcp"));
     DEBUGF(DHCP_DEBUG, ("dhcp_inform(): could not allocate dhcp_state"));  
530      return;      return;
531    }      }  
532    memset(state, 0, sizeof(struct dhcp_state));    memset(dhcp, 0, sizeof(struct dhcp));
533    
534    DEBUGF(DHCP_DEBUG, ("dhcp_inform(): allocated dhcp_state"));    DEBUGF(DHCP_DEBUG, ("dhcp_inform(): allocated dhcp"));
535    state->pcb = udp_new();    dhcp->pcb = udp_new();
536    if (state->pcb == NULL) {    if (dhcp->pcb == NULL) {
537      DEBUGF(DHCP_DEBUG, ("dhcp_inform(): could not obtain pcb"));      DEBUGF(DHCP_DEBUG, ("dhcp_inform(): could not obtain pcb"));
538      mem_free((void *)state);      mem_free((void *)dhcp);
539      return;      return;
540    }    }
541    DEBUGF(DHCP_DEBUG, ("dhcp_inform(): created new udp pcb"));    DEBUGF(DHCP_DEBUG, ("dhcp_inform(): created new udp pcb"));
   state->netif = netif;  
   /* we are last in list */  
   state->next = NULL;  
542    /* create and initialize the DHCP message header */    /* create and initialize the DHCP message header */
543    result = dhcp_create_request(state);    result = dhcp_create_request(dhcp);
544    if (result == ERR_OK)    if (result == ERR_OK) {
   {  
545    
546      dhcp_option(state, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);      dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
547      dhcp_option_byte(state, DHCP_INFORM);      dhcp_option_byte(dhcp, DHCP_INFORM);
548    
549      dhcp_option(state, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);      dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
550      dhcp_option_short(state, 576);      /* TODO: use netif->mtu ?! */
551        dhcp_option_short(dhcp, 576);
552    
553      dhcp_option_trailer(state);      dhcp_option_trailer(dhcp);
554    
555      pbuf_realloc(state->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + state->options_out_len);      pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
556    
557      udp_bind(state->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);      udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
558      udp_connect(state->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);      udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
559      udp_send(state->pcb, state->p_out);      udp_send(dhcp->pcb, dhcp->p_out);
560      udp_connect(state->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);      udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
561      dhcp_delete_request(state);      dhcp_delete_request(dhcp);
562    }    }
563    
564    if (state != NULL)    if (dhcp != NULL)
565    {    {
566      if (state->pcb != NULL) udp_remove(state->pcb);      if (dhcp->pcb != NULL) udp_remove(dhcp->pcb);
567      state->pcb = NULL;      dhcp->pcb = NULL;
568      mem_free((void *)state);      mem_free((void *)dhcp);
569    }    }
570  }  }
571    
# Line 649  void dhcp_inform(struct netif *netif) Line 576  void dhcp_inform(struct netif *netif)
576   * @param addr The IP address we received a reply from   * @param addr The IP address we received a reply from
577   *   *
578   */   */
579  void dhcp_arp_reply(struct ip_addr *addr)  void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
580  {  {
581    struct dhcp_state *list_state = client_list;    DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply()"));
582     DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply()"));    /* is this DHCP client doing an ARP check? */
583    /* loop through clients */    if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
584    while (list_state != NULL)      DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08lx", addr->addr));
585    {      /* did a host respond with the address we
586       DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply(): list_state %p", list_state));         were offered by the DHCP server? */
587      /* is this DHCP client doing an ARP check? */      if (ip_addr_cmp(addr, &dhcp->offered_ip_addr)) {
588      if (list_state->state == DHCP_CHECKING)        /* we will not accept the offered address */
589      {        DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply(): arp reply matched with offered address, declining"));
590        DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08lx", addr->addr));        dhcp_decline(netif);
       /* does a host respond with the address we  
          were offered by the DHCP server? */  
       if (ip_addr_cmp(addr, &list_state->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(list_state);  
       }  
591      }      }
     else  
     {  
       DEBUGF(DHCP_DEBUG, ("dhcp_arp_reply(): NOT CHECKING"));  
     }  
     /* proceed to next timer */  
     list_state = list_state->next;  
592    }    }
593  }  }
594    
# Line 686  void dhcp_arp_reply(struct ip_addr *addr Line 599  void dhcp_arp_reply(struct ip_addr *addr
599   * One reason to decline the lease is when we find out the address   * One reason to decline the lease is when we find out the address
600   * is already in use by another host (through ARP).   * is already in use by another host (through ARP).
601   */   */
602  static err_t dhcp_decline(struct dhcp_state *state)  static err_t dhcp_decline(struct netif *netif)
603  {  {
604      struct dhcp *dhcp = netif->dhcp;
605    err_t result = ERR_OK;    err_t result = ERR_OK;
606    u16_t msecs;    u16_t msecs;
607    DEBUGF(DHCP_DEBUG, ("dhcp_decline()"));    DEBUGF(DHCP_DEBUG, ("dhcp_decline()"));
608    dhcp_set_state(state, DHCP_BACKING_OFF);    dhcp_set_state(dhcp, DHCP_BACKING_OFF);
609    /* create and initialize the DHCP message header */    /* create and initialize the DHCP message header */
610    result = dhcp_create_request(state);    result = dhcp_create_request(dhcp);
611    if (result == ERR_OK)    if (result == ERR_OK)
612    {    {
613      dhcp_option(state, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);      dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
614      dhcp_option_byte(state, DHCP_DECLINE);      dhcp_option_byte(dhcp, DHCP_DECLINE);
615    
616      dhcp_option(state, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);      dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
617      dhcp_option_short(state, 576);      dhcp_option_short(dhcp, 576);
618    
619      dhcp_option_trailer(state);      dhcp_option_trailer(dhcp);
620      // resize pbuf to reflect true size of options      /* resize pbuf to reflect true size of options */
621      pbuf_realloc(state->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + state->options_out_len);      pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
622    
623      udp_bind(state->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);      udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
624      udp_connect(state->pcb, &state->server_ip_addr, DHCP_SERVER_PORT);      udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
625      udp_send(state->pcb, state->p_out);      udp_send(dhcp->pcb, dhcp->p_out);
626      dhcp_delete_request(state);      dhcp_delete_request(dhcp);
627    }    }
628    state->tries++;    dhcp->tries++;
629    msecs = 10*1000;    msecs = 10*1000;
630    state->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;    dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
631     DEBUGF(DHCP_DEBUG, ("dhcp_decline(): set request timeout %u msecs", msecs));     DEBUGF(DHCP_DEBUG, ("dhcp_decline(): set request timeout %u msecs", msecs));
632    return result;    return result;
633  }  }
# Line 724  static err_t dhcp_decline(struct dhcp_st Line 638  static err_t dhcp_decline(struct dhcp_st
638   * Start the DHCP process, discover a DHCP server.   * Start the DHCP process, discover a DHCP server.
639   *   *
640   */   */
641  static err_t dhcp_discover(struct dhcp_state *state)  static err_t dhcp_discover(struct netif *netif)
642  {  {
643      struct dhcp *dhcp = netif->dhcp;
644    err_t result = ERR_OK;    err_t result = ERR_OK;
645    u16_t msecs;    u16_t msecs;
646    DEBUGF(DHCP_DEBUG, ("dhcp_discover()"));    DEBUGF(DHCP_DEBUG, ("dhcp_discover()"));
647    ip_addr_set(&state->offered_ip_addr, IP_ADDR_ANY);    ip_addr_set(&dhcp->offered_ip_addr, IP_ADDR_ANY);
648    // create and initialize the DHCP message header    /* create and initialize the DHCP message header */
649    result = dhcp_create_request(state);    result = dhcp_create_request(dhcp);
650    if (result == ERR_OK)    if (result == ERR_OK)
651    {    {
652      dhcp_option(state, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);      dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
653      dhcp_option_byte(state, DHCP_DISCOVER);      dhcp_option_byte(dhcp, DHCP_DISCOVER);
654    
655      dhcp_option(state, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);      dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
656      dhcp_option_short(state, 576);      dhcp_option_short(dhcp, 576);
657    
658      dhcp_option(state, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);      dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 3);
659      dhcp_option_byte(state, DHCP_OPTION_SUBNET_MASK);      dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
660      dhcp_option_byte(state, DHCP_OPTION_ROUTER);      dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
661      dhcp_option_byte(state, DHCP_OPTION_BROADCAST);      dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
662    
663      dhcp_option_trailer(state);      dhcp_option_trailer(dhcp);
664    
665      pbuf_realloc(state->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + state->options_out_len);      pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
666    
667      udp_recv(state->pcb, dhcp_recv, state);      /* set receive callback function with netif as user data */
668      udp_bind(state->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);      udp_recv(dhcp->pcb, dhcp_recv, netif);
669      udp_connect(state->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);      udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
670        udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
671      udp_send(state->pcb, state->p_out);  
672      udp_bind(state->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);      udp_send(dhcp->pcb, dhcp->p_out);
673      udp_connect(state->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);      udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
674      dhcp_delete_request(state);      udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
675    }      dhcp_delete_request(dhcp);
676    state->tries++;    }
677    msecs = state->tries < 4 ? (state->tries + 1) * 1000 : 10 * 1000;    dhcp->tries++;
678    state->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;    msecs = dhcp->tries < 4 ? (dhcp->tries + 1) * 1000 : 10 * 1000;
679      dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
680     DEBUGF(DHCP_DEBUG, ("dhcp_discover(): set request timeout %u msecs", msecs));     DEBUGF(DHCP_DEBUG, ("dhcp_discover(): set request timeout %u msecs", msecs));
681    dhcp_set_state(state, DHCP_SELECTING);    dhcp_set_state(dhcp, DHCP_SELECTING);
682    return result;    return result;
683  }  }
684    
# Line 770  static err_t dhcp_discover(struct dhcp_s Line 686  static err_t dhcp_discover(struct dhcp_s
686  /**  /**
687   * Bind the interface to the offered IP address.   * Bind the interface to the offered IP address.
688   *   *
689     * @param netif network interface to bind to the offered address
690   */   */
691  static void dhcp_bind(struct dhcp_state *state)  static void dhcp_bind(struct netif *netif)
692  {  {
693      struct dhcp *dhcp = netif->dhcp;
694    struct ip_addr sn_mask, gw_addr;    struct ip_addr sn_mask, gw_addr;
695    dhcp_set_state(state, DHCP_BOUND);    
696    /* temporary DHCP lease? */    /* temporary DHCP lease? */
697    if (state->offered_t1_renew != 0xffffffffUL) {    if (dhcp->offered_t1_renew != 0xffffffffUL) {
698      /* set renewal period timer */      /* set renewal period timer */
699       DEBUGF(DHCP_DEBUG, ("dhcp_bind(): t1 renewal timer %lu secs", state->offered_t1_renew));      DEBUGF(DHCP_DEBUG, ("dhcp_bind(): t1 renewal timer %lu secs", dhcp->offered_t1_renew));
700       state->t1_timeout = (state->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;      dhcp->t1_timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
701      if (state->t1_timeout == 0) state->t1_timeout = 1;      if (dhcp->t1_timeout == 0) dhcp->t1_timeout = 1;
702       DEBUGF(DHCP_DEBUG, ("dhcp_bind(): set request timeout %u msecs", state->offered_t1_renew*1000));      DEBUGF(DHCP_DEBUG, ("dhcp_bind(): set request timeout %u msecs", dhcp->offered_t1_renew*1000));
703    }    }
704    /* set renewal period timer */    /* set renewal period timer */
705    if (state->offered_t2_rebind != 0xffffffffUL)    if (dhcp->offered_t2_rebind != 0xffffffffUL) {
706    {      DEBUGF(DHCP_DEBUG, ("dhcp_bind(): t2 rebind timer %lu secs", dhcp->offered_t2_rebind));
707       DEBUGF(DHCP_DEBUG, ("dhcp_bind(): t2 rebind timer %lu secs", state->offered_t2_rebind));      dhcp->t2_timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
708       state->t2_timeout = (state->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;      if (dhcp->t2_timeout == 0) dhcp->t2_timeout = 1;
709      if (state->t2_timeout == 0) state->t2_timeout = 1;      DEBUGF(DHCP_DEBUG, ("dhcp_bind(): set request timeout %u msecs", dhcp->offered_t2_rebind*1000));
      DEBUGF(DHCP_DEBUG, ("dhcp_bind(): set request timeout %u msecs", state->offered_t2_rebind*1000));  
710    }    }
711      /* copy offered network mask */
712    ip_addr_set(&sn_mask, &state->offered_sn_mask);    ip_addr_set(&sn_mask, &dhcp->offered_sn_mask);
713    
714    /* subnet mask not given? */    /* subnet mask not given? */
715    /* TODO: this is not a valid check. what if the network mask is 0??!! */    /* TODO: this is not a valid check. what if the network mask is 0??!! */
716    if (sn_mask.addr == 0)    if (sn_mask.addr == 0) {
   {  
717      /* choose a safe subnet mask given the network class */      /* choose a safe subnet mask given the network class */
718      u8_t first_octet = ip4_addr1(&sn_mask);      u8_t first_octet = ip4_addr1(&sn_mask);
719      if (first_octet <= 127) sn_mask.addr = htonl(0xff000000);      if (first_octet <= 127) sn_mask.addr = htonl(0xff000000);
720      else if (first_octet >= 192) sn_mask.addr = htonl(0xffffff00);      else if (first_octet >= 192) sn_mask.addr = htonl(0xffffff00);
721      else sn_mask.addr = htonl(0xffff0000);      else sn_mask.addr = htonl(0xffff0000);
722    }    }
   DEBUGF(DHCP_DEBUG, ("dhcp_bind(): SN: 0x%08lx", sn_mask.addr));  
   netif_set_netmask(state->netif, &sn_mask);  
723    
724    ip_addr_set(&gw_addr, &state->offered_gw_addr);    ip_addr_set(&gw_addr, &dhcp->offered_gw_addr);
725    /* gateway address not given? */    /* gateway address not given? */
726    if (gw_addr.addr == 0)    if (gw_addr.addr == 0) {
727    {      /* copy network address */
728      gw_addr.addr &= sn_mask.addr;      gw_addr.addr = (&dhcp->offered_ip_addr & sn_mask.addr);
729      gw_addr.addr |= 0x01000000;      /* use first host address on network as gateway */
730        gw_addr.addr |= htonl(0x00000001);
731    }    }
   DEBUGF(DHCP_DEBUG, ("dhcp_bind(): GW: 0x%08lx", gw_addr.addr));  
   netif_set_gw(state->netif, &gw_addr);  
732    
733    DEBUGF(DHCP_DEBUG, ("dhcp_bind(): IP: 0x%08lx", state->offered_ip_addr.addr));    DEBUGF(DHCP_DEBUG, ("dhcp_bind(): IP: 0x%08lx", dhcp->offered_ip_addr.addr));
734    netif_set_ipaddr(state->netif, &state->offered_ip_addr);    netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
735      DEBUGF(DHCP_DEBUG, ("dhcp_bind(): SN: 0x%08lx", sn_mask.addr));
736      netif_set_netmask(netif, &sn_mask);
737      DEBUGF(DHCP_DEBUG, ("dhcp_bind(): GW: 0x%08lx", gw_addr.addr));
738      netif_set_gw(netif, &gw_addr);
739      /* netif is now bound to DHCP leased address */
740      dhcp_set_state(dhcp, DHCP_BOUND);
741  }  }
742    
743  /**  /**
744   * Renew an existing DHCP lease at the involved DHCP server.   * Renew an existing DHCP lease at the involved DHCP server.
745   *   *
746     * @param netif network interface which must renew its lease
747   */   */
748  err_t dhcp_renew(struct dhcp_state *state)  err_t dhcp_renew(struct netif *netif)
749  {  {
750      struct dhcp *dhcp = netif->dhcp;
751    err_t result;    err_t result;
752    u16_t msecs;    u16_t msecs;
753    DEBUGF(DHCP_DEBUG, ("dhcp_renew()"));    DEBUGF(DHCP_DEBUG, ("dhcp_renew()"));
754    dhcp_set_state(state, DHCP_RENEWING);    dhcp_set_state(dhcp, DHCP_RENEWING);
755    
756    // create and initialize the DHCP message header    /* create and initialize the DHCP message header */
757    result = dhcp_create_request(state);    result = dhcp_create_request(dhcp);
758    if (result == ERR_OK)    if (result == ERR_OK) {
   {  
759    
760      dhcp_option(state, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);      dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
761      dhcp_option_byte(state, DHCP_REQUEST);      dhcp_option_byte(dhcp, DHCP_REQUEST);
762    
763      dhcp_option(state, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);      dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
764      dhcp_option_short(state, 576);      /* TODO: use netif->mtu in some way */
765        dhcp_option_short(dhcp, 576);
766    
767  #if 0  #if 0
768      dhcp_option(state, DHCP_OPTION_REQUESTED_IP, 4);      dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
769      dhcp_option_long(state, ntohl(state->offered_ip_addr.addr));      dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
770  #endif  #endif
771    
772  #if 0  #if 0
773      dhcp_option(state, DHCP_OPTION_SERVER_ID, 4);      dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
774      dhcp_option_long(state, ntohl(state->server_ip_addr.addr));      dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
775  #endif  #endif
776        /* append DHCP message trailer */
777        dhcp_option_trailer(dhcp);
778    
779      dhcp_option_trailer(state);      pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
   
     pbuf_realloc(state->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + state->options_out_len);  
780    
781      udp_bind(state->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);      udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
782      udp_connect(state->pcb, &state->server_ip_addr, DHCP_SERVER_PORT);      udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
783      udp_send(state->pcb, state->p_out);      udp_send(dhcp->pcb, dhcp->p_out);
784      dhcp_delete_request(state);      dhcp_delete_request(dhcp);
785    }    }
786    state->tries++;    dhcp->tries++;
787    // back-off on retries, but to a maximum of 20 seconds    /* back-off on retries, but to a maximum of 20 seconds */
788    msecs = state->tries < 10 ? state->tries * 2000 : 20 * 1000;    msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
789    state->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;    dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
790     DEBUGF(DHCP_DEBUG, ("dhcp_renew(): set request timeout %u msecs", msecs));     DEBUGF(DHCP_DEBUG, ("dhcp_renew(): set request timeout %u msecs", msecs));
791    return result;    return result;
792  }  }
# Line 873  err_t dhcp_renew(struct dhcp_state *stat Line 794  err_t dhcp_renew(struct dhcp_state *stat
794  /**  /**
795   * Rebind with a DHCP server for an existing DHCP lease.   * Rebind with a DHCP server for an existing DHCP lease.
796   *   *
797     * @param netif network interface which must rebind with a DHCP server
798   */   */
799  static err_t dhcp_rebind(struct dhcp_state *state)  static err_t dhcp_rebind(struct netif *netif)
800  {  {
801      struct dhcp *dhcp = netif->dhcp;
802    err_t result;    err_t result;
803    u16_t msecs;    u16_t msecs;
804    DEBUGF(DHCP_DEBUG, ("dhcp_rebind()"));    DEBUGF(DHCP_DEBUG, ("dhcp_rebind()"));
805    dhcp_set_state(state, DHCP_REBINDING);    dhcp_set_state(dhcp, DHCP_REBINDING);
806    
807    // create and initialize the DHCP message header    /* create and initialize the DHCP message header */
808    result = dhcp_create_request(state);    result = dhcp_create_request(dhcp);
809    if (result == ERR_OK)    if (result == ERR_OK)
810    {    {
811    
812      dhcp_option(state, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);      dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
813      dhcp_option_byte(state, DHCP_REQUEST);      dhcp_option_byte(dhcp, DHCP_REQUEST);
814    
815      dhcp_option(state, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);      dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
816      dhcp_option_short(state, 576);      dhcp_option_short(dhcp, 576);
817    
818  #if 0  #if 0
819      dhcp_option(state, DHCP_OPTION_REQUESTED_IP, 4);      dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
820      dhcp_option_long(state, ntohl(state->offered_ip_addr.addr));      dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
821    
822      dhcp_option(state, DHCP_OPTION_SERVER_ID, 4);      dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
823      dhcp_option_long(state, ntohl(state->server_ip_addr.addr));      dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
824  #endif  #endif
825    
826      dhcp_option_trailer(state);      dhcp_option_trailer(dhcp);
827    
828      pbuf_realloc(state->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + state->options_out_len);      pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
829    
830      udp_bind(state->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);      udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
831      udp_connect(state->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);      udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
832      udp_send(state->pcb, state->p_out);      udp_send(dhcp->pcb, dhcp->p_out);
833      udp_connect(state->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);      udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
834      dhcp_delete_request(state);      dhcp_delete_request(dhcp);
835    }    }
836    state->tries++;    dhcp->tries++;
837    msecs = state->tries < 10 ? state->tries * 1000 : 10 * 1000;    msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
838    state->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;    dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
839     DEBUGF(DHCP_DEBUG, ("dhcp_rebind(): set request timeout %u msecs", msecs));     DEBUGF(DHCP_DEBUG, ("dhcp_rebind(): set request timeout %u msecs", msecs));
840    return result;    return result;
841  }  }
842    
843  /**  /**
844   * Rebind with a DHCP server for an existing DHCP lease.   * Release a DHCP lease.
845   *   *
846     * @param netif network interface which must release its lease
847   */   */
848  static err_t dhcp_release(struct dhcp_state *state)  static err_t dhcp_release(struct netif *netif)
849  {  {
850      struct dhcp *dhcp = netif->dhcp;
851    err_t result;    err_t result;
852    u16_t msecs;    u16_t msecs;
853    DEBUGF(DHCP_DEBUG, ("dhcp_release()"));    DEBUGF(DHCP_DEBUG, ("dhcp_release()"));
854     // and idle DHCP client    /* idle DHCP client */
855    dhcp_set_state(state, DHCP_OFF);    dhcp_set_state(dhcp, DHCP_OFF);
   
   // create and initialize the DHCP message header  
   result = dhcp_create_request(state);  
   if (result == ERR_OK)  
   {  
     dhcp_option(state, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);  
     dhcp_option_byte(state, DHCP_RELEASE);  
856    
857      dhcp_option_trailer(state);    /* create and initialize the DHCP message header */
858      result = dhcp_create_request(dhcp);
859      pbuf_realloc(state->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + state->options_out_len);    if (result == ERR_OK) {
860        dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
861      udp_bind(state->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);      dhcp_option_byte(dhcp, DHCP_RELEASE);
862      udp_connect(state->pcb, &state->server_ip_addr, DHCP_SERVER_PORT);  
863      udp_send(state->pcb, state->p_out);      dhcp_option_trailer(dhcp);
864      dhcp_delete_request(state);  
865    }      pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
866    state->tries++;  
867    msecs = state->tries < 10 ? state->tries * 1000 : 10 * 1000;      udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
868    state->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;      udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
869        udp_send(dhcp->pcb, dhcp->p_out);
870        dhcp_delete_request(dhcp);
871      }
872      dhcp->tries++;
873      msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
874      dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
875     DEBUGF(DHCP_DEBUG, ("dhcp_release(): set request timeout %u msecs", msecs));     DEBUGF(DHCP_DEBUG, ("dhcp_release(): set request timeout %u msecs", msecs));
876    // remove IP address from interface    /* remove IP address from interface */
877    netif_set_ipaddr(state->netif, IP_ADDR_ANY);    netif_set_ipaddr(netif, IP_ADDR_ANY);
878    netif_set_gw(state->netif, IP_ADDR_ANY);    netif_set_gw(netif, IP_ADDR_ANY);
879    netif_set_netmask(state->netif, IP_ADDR_ANY);    netif_set_netmask(netif, IP_ADDR_ANY);
880      /* TODO: netif_down(netif); */
881    return result;    return result;
882  }  }
883  /**  /**
884   * Remove the DHCP client from the interface.   * Remove the DHCP client from the interface.
885   *   *
886   * @param state The DHCP client state   * @param netif The network interface to stop DHCP on
887   */   */
888  void dhcp_stop(struct dhcp_state *state)  void dhcp_stop(struct netif *netif)
889  {  {
890    struct dhcp_state *list_state = client_list;    struct dhcp *dhcp = netif->dhcp;
891    DEBUGF(DHCP_DEBUG, ("dhcp_stop()"));    DEBUGF(DHCP_DEBUG, ("dhcp_stop()"));
892    LWIP_ASSERT("dhcp_stop: state != NULL", state != NULL);    LWIP_ASSERT("dhcp_stop: dhcp != NULL", dhcp != NULL);
893    LWIP_ASSERT("dhcp_stop: state->pcb != NULL", state->pcb != NULL);    LWIP_ASSERT("dhcp_stop: dhcp->pcb != NULL", dhcp->pcb != NULL);
894      /* netif is DHCP configured? */
895    if (state != NULL)    if (dhcp != NULL)
896    {    {
897      if (state->pcb != NULL)      if (dhcp->pcb != NULL)
898      {      {
899        udp_remove(state->pcb);        udp_remove(dhcp->pcb);
900        state->pcb = NULL;        dhcp->pcb = NULL;
901      }      }
902      if (state->p != NULL)      if (dhcp->p != NULL)
903      {      {
904        pbuf_free(state->p);        pbuf_free(dhcp->p);
905        state->p = NULL;        dhcp->p = NULL;
     }  
     mem_free((void *)state);  
     // at head of list?  
     if (list_state == state)  
     {  
       // remove ourselves from head  
       client_list = state->next;  
     }  
     // not at head  
     else  
     {  
       // see if we can find a predecessor?  
       while ((list_state != NULL) && (list_state->next != state))  
       {  
         // proceed to next state, if any  
         list_state = list_state->next;  
       }  
       // found a predecessor?  
       if (list_state != NULL)  
       {  
         // remove ourselves from list  
         list_state->next = state->next;  
       }  
906      }      }
907        mem_free((void *)dhcp);
908        netif->dhcp = NULL;
909    }    }
910  }  }
911    
# Line 1012  void dhcp_stop(struct dhcp_state *state) Line 916  void dhcp_stop(struct dhcp_state *state)
916   *   *
917   * TODO: we might also want to reset the timeout here?   * TODO: we might also want to reset the timeout here?
918   */   */
919  static void dhcp_set_state(struct dhcp_state *state, unsigned char new_state)  static void dhcp_set_state(struct dhcp *dhcp, unsigned char new_state)
920  {  {
921    if (new_state != state->state)    if (new_state != dhcp->state)
922    {    {
923       state->state = new_state;      dhcp->state = new_state;
924      state->tries = 0;      dhcp->tries = 0;
925    }    }
926  }  }
927    
# Line 1026  static void dhcp_set_state(struct dhcp_s Line 930  static void dhcp_set_state(struct dhcp_s
930   * DHCP message.   * DHCP message.
931   *   *
932   */   */
933  static void dhcp_option(struct dhcp_state *state, u8_t option_type, u8_t option_len)  static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len)
934  {  {
935    LWIP_ASSERT("dhcp_option_short: state->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", state->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN);    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);
936    state->msg_out->options[state->options_out_len++] = option_type;    dhcp->msg_out->options[dhcp->options_out_len++] = option_type;
937    state->msg_out->options[state->options_out_len++] = option_len;    dhcp->msg_out->options[dhcp->options_out_len++] = option_len;
938  }  }
939  /*  /*
940   * Concatenate a single byte to the outgoing DHCP message.   * Concatenate a single byte to the outgoing DHCP message.
941   *   *
942   */   */
943  static void dhcp_option_byte(struct dhcp_state *state, u8_t value)  static void dhcp_option_byte(struct dhcp *dhcp, u8_t value)
944  {  {
945    LWIP_ASSERT("dhcp_option_short: state->options_out_len < DHCP_OPTIONS_LEN", state->options_out_len < DHCP_OPTIONS_LEN);    LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN);
946    state->msg_out->options[state->options_out_len++] = value;    dhcp->msg_out->options[dhcp->options_out_len++] = value;
947  }                              }                            
948  static void dhcp_option_short(struct dhcp_state *state, u16_t value)  static void dhcp_option_short(struct dhcp *dhcp, u16_t value)
949  {  {
950    LWIP_ASSERT("dhcp_option_short: state->options_out_len + 2 <= DHCP_OPTIONS_LEN", state->options_out_len + 2 <= DHCP_OPTIONS_LEN);    LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN);
951    state->msg_out->options[state->options_out_len++] = (value & 0xff00U) >> 8;    dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0xff00U) >> 8;
952    state->msg_out->options[state->options_out_len++] =  value & 0x00ffU;    dhcp->msg_out->options[dhcp->options_out_len++] =  value & 0x00ffU;
953  }  }
954  static void dhcp_option_long(struct dhcp_state *state, u32_t value)  static void dhcp_option_long(struct dhcp *dhcp, u32_t value)
955  {  {
956    LWIP_ASSERT("dhcp_option_long: state->options_out_len + 4 <= DHCP_OPTIONS_LEN", state->options_out_len + 4 <= DHCP_OPTIONS_LEN);    LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN);
957    state->msg_out->options[state->options_out_len++] = (value & 0xff000000UL) >> 24;    dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0xff000000UL) >> 24;
958    state->msg_out->options[state->options_out_len++] = (value & 0x00ff0000UL) >> 16;    dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0x00ff0000UL) >> 16;
959    state->msg_out->options[state->options_out_len++] = (value & 0x0000ff00UL) >> 8;    dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0x0000ff00UL) >> 8;
960    state->msg_out->options[state->options_out_len++] = (value & 0x000000ffUL);    dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0x000000ffUL);
961  }  }
962    
963  /**  /**
# Line 1062  static void dhcp_option_long(struct dhcp Line 966  static void dhcp_option_long(struct dhcp
966   *   *
967   *   *
968   */   */
969  static err_t dhcp_unfold_reply(struct dhcp_state *state)  static err_t dhcp_unfold_reply(struct dhcp *dhcp)
970  {  {
971    struct pbuf *p = state->p;    struct pbuf *p = dhcp->p;
972    u8_t *ptr;    u8_t *ptr;
973    u16_t i;    u16_t i;
974    u16_t j = 0;    u16_t j = 0;
975    state->msg_in = NULL;    dhcp->msg_in = NULL;
976    state->options_in = NULL;    dhcp->options_in = NULL;
977    /* options present? */    /* options present? */
978    if (state->p->tot_len > sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN)    if (dhcp->p->tot_len > sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN)
979    {    {
980      state->options_in_len = state->p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);      dhcp->options_in_len = dhcp->p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
981      state->options_in = mem_malloc(state->options_in_len);      dhcp->options_in = mem_malloc(dhcp->options_in_len);
982      if (state->options_in == NULL)      if (dhcp->options_in == NULL)
983      {      {
984        DEBUGF(DHCP_DEBUG, ("dhcp_unfold_reply(): could not allocate state->options"));        DEBUGF(DHCP_DEBUG, ("dhcp_unfold_reply(): could not allocate dhcp->options"));
985        return ERR_MEM;        return ERR_MEM;
986      }      }
987    }    }
988    state->msg_in = mem_malloc(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);    dhcp->msg_in = mem_malloc(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
989    if (state->msg_in == NULL)    if (dhcp->msg_in == NULL)
990    {    {
991      DEBUGF(DHCP_DEBUG, ("dhcp_unfold_reply(): could not allocate state->msg_in"));      DEBUGF(DHCP_DEBUG, ("dhcp_unfold_reply(): could not allocate dhcp->msg_in"));
992      mem_free((void *)state->options_in);      mem_free((void *)dhcp->options_in);
993      state->options_in = NULL;      dhcp->options_in = NULL;
994      return ERR_MEM;      return ERR_MEM;
995    }    }
996    
997    ptr = (u8_t *)state->msg_in;    ptr = (u8_t *)dhcp->msg_in;
998    /* proceed through struct dhcp_msg */    /* proceed through struct dhcp_msg */
999    for (i = 0; i < sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN; i++)    for (i = 0; i < sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN; i++)
1000    {    {
# Line 1103  static err_t dhcp_unfold_reply(struct dh Line 1007  static err_t dhcp_unfold_reply(struct dh
1007        j = 0;        j = 0;
1008      }      }
1009    }    }
1010    DEBUGF(DHCP_DEBUG, ("dhcp_unfold_reply(): copied %u bytes into state->msg_in[]", i));    DEBUGF(DHCP_DEBUG, ("dhcp_unfold_reply(): copied %u bytes into dhcp->msg_in[]", i));
1011    if (state->options_in != NULL)    if (dhcp->options_in != NULL) {
1012    {      ptr = (u8_t *)dhcp->options_in;
     ptr = (u8_t *)state->options_in;  
1013      /* proceed through options */      /* proceed through options */
1014      for (i = 0; i < state->options_in_len; i++)      for (i = 0; i < dhcp->options_in_len; i++) {
     {  
1015        *ptr++ = ((u8_t *)p->payload)[j++];        *ptr++ = ((u8_t *)p->payload)[j++];
1016        /* reached end of pbuf? */        /* reached end of pbuf? */
1017        if (j == p->len)        if (j == p->len) {
       {  
1018          /* proceed to next pbuf in chain */          /* proceed to next pbuf in chain */
1019          p = p->next;          p = p->next;
1020          j = 0;          j = 0;
1021        }        }
1022      }      }
1023      DEBUGF(DHCP_DEBUG, ("dhcp_unfold_reply(): copied %u bytes to state->options_in[]", i));      DEBUGF(DHCP_DEBUG, ("dhcp_unfold_reply(): copied %u bytes to dhcp->options_in[]", i));
1024    }    }
1025    return ERR_OK;    return ERR_OK;
1026  }  }
# Line 1129  static err_t dhcp_unfold_reply(struct dh Line 1030  static err_t dhcp_unfold_reply(struct dh
1030   * its DHCP options.   * its DHCP options.
1031   *   *
1032   */   */
1033  static void dhcp_free_reply(struct dhcp_state *state)  static void dhcp_free_reply(struct dhcp *dhcp)
1034  {  {
1035    mem_free((void *)state->msg_in);    if (dhcp->msg_in != NULL) {
1036    mem_free((void *)state->options_in);      mem_free((void *)dhcp->msg_in);
1037        dhcp->msg_in = NULL;
1038      }
1039      if (dhcp->options_in) {
1040        mem_free((void *)dhcp->options_in);
1041        dhcp->options_in = NULL;
1042        dhcp->options_in_len = 0;
1043      }
1044    DEBUGF(DHCP_DEBUG, ("dhcp_free_reply(): freed"));    DEBUGF(DHCP_DEBUG, ("dhcp_free_reply(): freed"));
   state->msg_in = NULL;  
   state->options_in = NULL;  
   state->options_in_len = 0;  
1045  }  }
1046    
1047    
1048  /**  /**
1049   * Match incoming DHCP messages against a DHCP client, and trigger its state machine   * If an incoming DHCP message is in response to use, then trigger the state machine
1050   */   */
1051  static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)  static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
1052  {  {
1053    struct dhcp_state *state = (struct dhcp_state *)arg;    struct netif *netif = (struct netif *)arg;
1054      struct dhcp *dhcp = netif->dhcp;
1055    struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload;    struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload;
1056      u8_t *options_ptr;
1057      u8_t msg_type;
1058      u8_t i;
1059    DEBUGF(DHCP_DEBUG, ("dhcp_recv()"));    DEBUGF(DHCP_DEBUG, ("dhcp_recv()"));
1060    DEBUGF(DHCP_DEBUG, ("pbuf->len = %u", p->len));    DEBUGF(DHCP_DEBUG, ("pbuf->len = %u", p->len));
1061    DEBUGF(DHCP_DEBUG, ("pbuf->tot_len = %u", p->tot_len));    DEBUGF(DHCP_DEBUG, ("pbuf->tot_len = %u", p->tot_len));
1062    state->p = p;    dhcp->p = p;
1063    if (reply_msg->op == DHCP_BOOTREPLY)    if (reply_msg->op != DHCP_BOOTREPLY) {
1064    {      DEBUGF(DHCP_DEBUG, ("not a DHCP reply message, but type %u", reply_msg->op));
1065      DEBUGF(DHCP_DEBUG, ("state->netif->hwaddr = %02x:%02x:%02x:%02x:%02x:%02x",      pbuf_free(p);
1066        state->netif->hwaddr[0], state->netif->hwaddr[1], state->netif->hwaddr[2],    }
1067        state->netif->hwaddr[3], state->netif->hwaddr[4],  state->netif->hwaddr[5]));    /* iterate through hardware address and match against DHCP message */
1068      // TODO: Add multi network interface support, look up the targetted    for (i = 0; i < netif->hwaddr_len; i++) {
1069      // interface here.      if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
1070      if ((state->netif->hwaddr[0] == reply_msg->chaddr[0]) &&        DEBUGF(DHCP_DEBUG, ("netif->hwaddr[%u]==%02x != reply_msg->chaddr[%u]==%02x",
1071          (state->netif->hwaddr[1] == reply_msg->chaddr[1]) &&          i, netif->hwaddr[i], i, reply_msg->chaddr[i]));
1072          (state->netif->hwaddr[2] == reply_msg->chaddr[2]) &&        pbuf_free(p);
1073          (state->netif->hwaddr[3] == reply_msg->chaddr[3]) &&        return;
1074          (state->netif->hwaddr[4] == reply_msg->chaddr[4]) &&      }
1075          (state->netif->hwaddr[5] == reply_msg->chaddr[5]))    }
1076      {    /* match transaction ID against what we expected */
1077        // check if the transaction ID matches    if (ntohl(reply_msg->xid) != dhcp->xid) {
1078        if (ntohl(reply_msg->xid) == state->xid)      DEBUGF(DHCP_DEBUG, ("transaction id mismatch"));
1079        {      pbuf_free(p);
1080          // option fields could be unfold?      return;
1081          if (dhcp_unfold_reply(state) == ERR_OK)    }
1082          {    /* option fields could be unfold? */
1083            u8_t *options_ptr = NULL;    if (dhcp_unfold_reply(dhcp) != ERR_OK) {
1084            DEBUGF(DHCP_DEBUG, ("searching DHCP_OPTION_MESSAGE_TYPE"));      DEBUGF(DHCP_DEBUG, ("problem unfolding DHCP message - too short on memory?"));
1085            options_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_MESSAGE_TYPE);      pbuf_free(p);
1086            if (options_ptr != NULL)      return;
1087            {    }
1088              u8_t msg_type = dhcp_get_option_byte(options_ptr + 2);    
1089              if (msg_type == DHCP_ACK)    DEBUGF(DHCP_DEBUG, ("searching DHCP_OPTION_MESSAGE_TYPE"));
1090              {    /* obtain pointer to DHCP message type */
1091                DEBUGF(DHCP_DEBUG, ("DHCP_ACK received"));    options_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_MESSAGE_TYPE);
1092                if (state->state == DHCP_REQUESTING)    if (options_ptr == NULL) {
1093                {      DEBUGF(DHCP_DEBUG, ("DHCP_OPTION_MESSAGE_TYPE option not found"));
1094                  dhcp_handle_ack(state);      pbuf_free(p);
1095                  state->request_timeout = 0;      return;
1096      }  
1097    
1098      /* read DHCP message type */
1099      msg_type = dhcp_get_option_byte(options_ptr + 2);
1100      /* message type is DHCP ACK? */
1101      if (msg_type == DHCP_ACK) {
1102        DEBUGF(DHCP_DEBUG, ("DHCP_ACK received"));
1103        /* in requesting state? */
1104        if (dhcp->state == DHCP_REQUESTING) {
1105          dhcp_handle_ack(dhcp);
1106          dhcp->request_timeout = 0;
1107  #if DHCP_DOES_ARP_CHECK  #if DHCP_DOES_ARP_CHECK
1108                  dhcp_check(state);        /* check if the acknowledged lease address is already in use */
1109          dhcp_check(netif);
1110  #else  #else
1111                  dhcp_bind(state);        /* bind interface to the acknowledged lease address */
1112          dhcp_bind(netif);
1113  #endif  #endif
               }  
               else if ((state->state == DHCP_REBOOTING) || (state->state == DHCP_REBINDING) ||(state->state == DHCP_RENEWING))  
               {  
                 state->request_timeout = 0;  
                 dhcp_bind(state);  
               }  
             }  
             // received a DHCP_NAK in appropriate state?  
             else if ((msg_type == DHCP_NAK) &&  
               ((state->state == DHCP_REBOOTING) || (state->state == DHCP_REQUESTING) ||  
               (state->state == DHCP_REBINDING) || (state->state == DHCP_RENEWING  )))  
             {  
               DEBUGF(DHCP_DEBUG, ("DHCP_NAK received"));  
               state->request_timeout = 0;  
               dhcp_handle_nak(state);  
             }  
             // received a DHCP_OFFER in DHCP_SELECTING state?  
             else if ((msg_type == DHCP_OFFER) && (state->state == DHCP_SELECTING))  
             {  
               DEBUGF(DHCP_DEBUG, ("DHCP_OFFER received in DHCP_SELECTING state"));  
               state->request_timeout = 0;  
               dhcp_handle_offer(state);  
             }  
           }  
           else  
           {  
             DEBUGF(DHCP_DEBUG, ("DHCP_OPTION_MESSAGE_TYPE option not found"));  
           }  
           dhcp_free_reply(state);  
         }  
       }  
       else  
       {  
         DEBUGF(DHCP_DEBUG, ("reply_msg->xid=%lx does not match with state->xid=%lx",  
           ntohl(reply_msg->xid), state->xid));      
       }  
     }  
     else  
     {  
       DEBUGF(DHCP_DEBUG, ("hardware address did not match"));      
       DEBUGF(DHCP_DEBUG, ("reply_msg->chaddr = %02x:%02x:%02x:%02x:%02x:%02x",  
         reply_msg->chaddr[0], reply_msg->chaddr[1], reply_msg->chaddr[2],  
         reply_msg->chaddr[3], reply_msg->chaddr[4],  reply_msg->chaddr[5]));  
1114      }      }
1115        /* already bound to the given lease address? */
1116        else if ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING)) {
1117          dhcp->request_timeout = 0;
1118          dhcp_bind(netif);
1119        }
1120      }
1121      /* received a DHCP_NAK in appropriate state? */
1122      else if ((msg_type == DHCP_NAK) &&
1123        ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) ||
1124         (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING  ))) {
1125        DEBUGF(DHCP_DEBUG, ("DHCP_NAK received"));
1126        dhcp->request_timeout = 0;
1127        dhcp_handle_nak(dhcp);
1128      }
1129      /* received a DHCP_OFFER in DHCP_SELECTING state? */
1130      else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) {
1131        DEBUGF(DHCP_DEBUG, ("DHCP_OFFER received in DHCP_SELECTING state"));
1132        dhcp->request_timeout = 0;
1133        /* remember offered lease */
1134        dhcp_handle_offer(dhcp);
1135    }    }
   else  
   {  
     DEBUGF(DHCP_DEBUG, ("not a DHCP reply message, but type %u", reply_msg->op));  
   }  
   
1136    pbuf_free(p);    pbuf_free(p);
1137  }  }
1138    
1139    
1140  static err_t dhcp_create_request(struct dhcp_state *state)  static err_t dhcp_create_request(struct dhcp *dhcp)
1141  {  {
1142    u16_t i;    u16_t i;
1143    LWIP_ASSERT("dhcp_create_request: state->p_out == NULL", state->p_out == NULL);    LWIP_ASSERT("dhcp_create_request: dhcp->p_out == NULL", dhcp->p_out == NULL);
1144    LWIP_ASSERT("dhcp_create_request: state->msg_out == NULL", state->msg_out == NULL);    LWIP_ASSERT("dhcp_create_request: dhcp->msg_out == NULL", dhcp->msg_out == NULL);
1145    state->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);    dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
1146    if (state->p_out == NULL)    if (dhcp->p_out == NULL) {
1147    {      DEBUGF(DHCP_DEBUG, ("dhcp_create_request(): could not allocate pbuf"));
      DEBUGF(DHCP_DEBUG, ("dhcp_create_request(): could not allocate pbuf"));  
1148      return ERR_MEM;      return ERR_MEM;
1149    }    }
1150    state->xid = xid;      /* give unique transaction identifier to this request */
1151    xid++;    dhcp->xid = xid++;  
1152    
1153    state->msg_out = (struct dhcp_msg *)state->p_out->payload;    dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload;
1154    
1155    state->msg_out->op = DHCP_BOOTREQUEST;      dhcp->msg_out->op = DHCP_BOOTREQUEST;
1156    state->msg_out->htype = DHCP_HTYPE_ETH;      /* TODO: make link layer independent */  
1157    state->msg_out->hlen = DHCP_HLEN_ETH;      dhcp->msg_out->htype = DHCP_HTYPE_ETH;  
1158    state->msg_out->hops = 0;    /* TODO: make link layer independent */  
1159    state->msg_out->xid = htonl(state->xid);      dhcp->msg_out->hlen = DHCP_HLEN_ETH;  
1160    state->msg_out->secs = 0;    dhcp->msg_out->hops = 0;
1161    state->msg_out->flags = 0;    dhcp->msg_out->xid = htonl(dhcp->xid);  
1162    state->msg_out->ciaddr = state->netif->ip_addr.addr;    dhcp->msg_out->secs = 0;
1163    state->msg_out->yiaddr = 0;    dhcp->msg_out->flags = 0;
1164    state->msg_out->siaddr = 0;    dhcp->msg_out->ciaddr = netif->ip_addr.addr;
1165    state->msg_out->giaddr = 0;    dhcp->msg_out->yiaddr = 0;
1166    for (i = 0; i < DHCP_CHADDR_LEN; i++) state->msg_out->chaddr[i] = state->netif->hwaddr[i];    dhcp->msg_out->siaddr = 0;
1167    for (i = 0; i < DHCP_SNAME_LEN; i++) state->msg_out->sname[i] = 0;    dhcp->msg_out->giaddr = 0;
1168    for (i = 0; i < DHCP_FILE_LEN; i++) state->msg_out->file[i] = 0;    for (i = 0; i < DHCP_CHADDR_LEN; i++) {
1169    state->msg_out->cookie = htonl(0x63825363UL);      /* copy netif hardware address, pad with zeroes */
1170    state->options_out_len = 0;      dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0/* pad byte*/;
1171    // fill options field with an incrementing array (for debugging purposes)    }
1172    for (i = 0; i < DHCP_OPTIONS_LEN; i++) state->msg_out->options[i] = i;    for (i = 0; i < DHCP_SNAME_LEN; i++) dhcp->msg_out->sname[i] = 0;
1173      for (i = 0; i < DHCP_FILE_LEN; i++) dhcp->msg_out->file[i] = 0;
1174      dhcp->msg_out->cookie = htonl(0x63825363UL);
1175      dhcp->options_out_len = 0;
1176      /* fill options field with an incrementing array (for debugging purposes) */
1177      for (i = 0; i < DHCP_OPTIONS_LEN; i++) dhcp->msg_out->options[i] = i;
1178    return ERR_OK;    return ERR_OK;
1179  }  }
1180    
1181  static void dhcp_delete_request(struct dhcp_state *state)  static void dhcp_delete_request(struct dhcp *dhcp)
1182  {  {
1183    LWIP_ASSERT("dhcp_free_msg: state->p_out != NULL", state->p_out != NULL);    LWIP_ASSERT("dhcp_free_msg: dhcp->p_out != NULL", dhcp->p_out != NULL);
1184    LWIP_ASSERT("dhcp_free_msg: state->msg_out != NULL", state->msg_out != NULL);    LWIP_ASSERT("dhcp_free_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL);
1185    pbuf_free(state->p_out);    pbuf_free(dhcp->p_out);
1186    state->p_out = NULL;    dhcp->p_out = NULL;
1187    state->msg_out = NULL;    dhcp->msg_out = NULL;
1188  }  }
1189    
1190  /**  /**
1191   * Add a DHCP message trailer   * Add a DHCP message trailer
1192   *   *
1193   * Adds the END option to the DHCP message, and up to   * Adds the END option to the DHCP message, and if
1194   * three padding bytes.   * necessary, up to three padding bytes.
1195   */   */
1196    
1197  static void dhcp_option_trailer(struct dhcp_state *state)  static void dhcp_option_trailer(struct dhcp *dhcp)
1198  {  {
1199    LWIP_ASSERT("dhcp_option_trailer: state->msg_out != NULL", state->msg_out != NULL);    LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL", dhcp->msg_out != NULL);
1200    LWIP_ASSERT("dhcp_option_trailer: state->options_out_len < DHCP_OPTIONS_LEN", state->options_out_len < DHCP_OPTIONS_LEN);    LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN);
1201    state->msg_out->options[state->options_out_len++] = DHCP_OPTION_END;    dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
1202    // packet is still too small, or not 4 byte aligned?    /* packet is too small, or not 4 byte aligned? */
1203    while ((state->options_out_len < DHCP_MIN_OPTIONS_LEN) || (state->options_out_len & 3))    while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) {
1204    {      /* DEBUGF(DHCP_DEBUG, ("dhcp_option_trailer: dhcp->options_out_len=%u, DHCP_OPTIONS_LEN=%u", dhcp->options_out_len, DHCP_OPTIONS_LEN)); */
1205      //DEBUGF(DHCP_DEBUG, ("dhcp_option_trailer: state->options_out_len=%u, DHCP_OPTIONS_LEN=%u", state->options_out_len, DHCP_OPTIONS_LEN));      LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN);
1206      LWIP_ASSERT("dhcp_option_trailer: state->options_out_len < DHCP_OPTIONS_LEN", state->options_out_len < DHCP_OPTIONS_LEN);      /* add a fill/padding byte */
1207      state->msg_out->options[state->options_out_len++] = 0;      dhcp->msg_out->options[dhcp->options_out_len++] = 0;
1208    }    }
1209  }  }
1210    
# Line 1319  static void dhcp_option_trailer(struct d Line 1217  static void dhcp_option_trailer(struct d
1217   * @return a byte offset into the UDP message where the option was found, or   * @return a byte offset into the UDP message where the option was found, or
1218   * zero if the given option was not found.   * zero if the given option was not found.
1219   */   */
1220  static u8_t *dhcp_get_option_ptr(struct dhcp_state *state, u8_t option_type)  static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
1221  {  {
1222    u8_t overload = DHCP_OVERLOAD_NONE;    u8_t overload = DHCP_OVERLOAD_NONE;
1223    
1224    // options available?    /* options available? */
1225    if ((state->options_in != NULL) && (state->options_in_len > 0))    if ((dhcp->options_in != NULL) && (dhcp->options_in_len > 0)) {
1226    {      /* start with options field */
1227      // start with options field      u8_t *options = (u8_t *)dhcp->options_in;
     u8_t *options = (u8_t *)state->options_in;  
1228      u16_t offset = 0;      u16_t offset = 0;
1229      // at least 1 byte to read and no end marker, then at least 3 bytes to read?      /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
1230      while ((offset < state->options_in_len) && (options[offset] != DHCP_OPTION_END))      while ((offset < dhcp->options_in_len) && (options[offset] != DHCP_OPTION_END)) {
1231      {        /* DEBUGF(DHCP_DEBUG, ("msg_offset=%u, q->len=%u", msg_offset, q->len)); */
1232        //DEBUGF(DHCP_DEBUG, ("msg_offset=%u, q->len=%u", msg_offset, q->len));        /* are the sname and/or file field overloaded with options? */
1233        // are the sname and/or file field overloaded with options?        if (options[offset] == DHCP_OPTION_OVERLOAD) {
1234        if (options[offset] == DHCP_OPTION_OVERLOAD)          DEBUGF(DHCP_DEBUG, ("overloaded message detected"));
1235        {          /* skip option type and length */
          DEBUGF(DHCP_DEBUG, ("overloaded message detected"));  
         // skip option type and length  
1236          offset += 2;          offset += 2;
1237          overload = options[offset++];          overload = options[offset++];
1238        }        }
1239        // requested option found        /* requested option found */
1240        else if (options[offset] == option_type)        else if (options[offset] == option_type) {
1241        {          DEBUGF(DHCP_DEBUG, ("option found at offset %u in options", offset));
          DEBUGF(DHCP_DEBUG, ("option found at offset %u in options", offset));  
1242          return &options[offset];          return &options[offset];
1243        }        /* skip option */
1244        // skip option        } else {
        else  
       {  
1245           DEBUGF(DHCP_DEBUG, ("skipping option %u in options", options[offset]));           DEBUGF(DHCP_DEBUG, ("skipping option %u in options", options[offset]));
1246          // skip option type          /* skip option type */
1247          offset++;          offset++;
1248          // skip option length, and then length bytes          /* skip option length, and then length bytes */
1249          offset += 1 + options[offset];          offset += 1 + options[offset];
1250        }        }
1251      }      }
1252      // is this an overloaded message?      /* is this an overloaded message? */
1253      if (overload != DHCP_OVERLOAD_NONE)      if (overload != DHCP_OVERLOAD_NONE) {
     {  
1254        u16_t field_len;        u16_t field_len;
1255        if (overload == DHCP_OVERLOAD_FILE)        if (overload == DHCP_OVERLOAD_FILE) {
       {  
1256          DEBUGF(DHCP_DEBUG, ("overloaded file field"));          DEBUGF(DHCP_DEBUG, ("overloaded file field"));
1257          options = (u8_t *)&state->msg_in->file;          options = (u8_t *)&dhcp->msg_in->file;
1258          field_len = DHCP_FILE_LEN;          field_len = DHCP_FILE_LEN;
1259        }        } else if (overload == DHCP_OVERLOAD_SNAME) {
       else if (overload == DHCP_OVERLOAD_SNAME)  
       {  
1260          DEBUGF(DHCP_DEBUG, ("overloaded sname field"));          DEBUGF(DHCP_DEBUG, ("overloaded sname field"));
1261          options = (u8_t *)&state->msg_in->sname;          options = (u8_t *)&dhcp->msg_in->sname;
1262          field_len = DHCP_SNAME_LEN;          field_len = DHCP_SNAME_LEN;
1263        }        /* TODO: check if else if () is necessary */
1264        else // TODO: check if else if () is necessary        } else {
       {  
1265          DEBUGF(DHCP_DEBUG, ("overloaded sname and file field"));          DEBUGF(DHCP_DEBUG, ("overloaded sname and file field"));
1266          options = (u8_t *)&state->msg_in->sname;          options = (u8_t *)&dhcp->msg_in->sname;
1267          field_len = DHCP_FILE_LEN + DHCP_SNAME_LEN;          field_len = DHCP_FILE_LEN + DHCP_SNAME_LEN;
1268        }        }
1269        offset = 0;        offset = 0;
1270    
1271        // at least 1 byte to read and no end marker        /* at least 1 byte to read and no end marker */
1272        while ((offset < field_len) && (options[offset] != DHCP_OPTION_END))        while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) {
1273        {          if (options[offset] == option_type) {
         if (options[offset] == option_type)  
         {  
1274             DEBUGF(DHCP_DEBUG, ("option found at offset=%u", offset));             DEBUGF(DHCP_DEBUG, ("option found at offset=%u", offset));
1275            return &options[offset];            return &options[offset];
1276          }          /* skip option */
1277          // skip option          } else {
1278           else            DEBUGF(DHCP_DEBUG, ("skipping option %u", options[offset]));
1279          {            /* skip option type */
            DEBUGF(DHCP_DEBUG, ("skipping option %u", options[offset]));  
           // skip option type  
1280            offset++;            offset++;
1281            offset += 1 + options[offset];            offset += 1 + options[offset];
1282          }          }
# Line 1452  static u32_t dhcp_get_option_long(u8_t * Line 1335  static u32_t dhcp_get_option_long(u8_t *
1335    DEBUGF(DHCP_DEBUG, ("option long value=%lu", value));    DEBUGF(DHCP_DEBUG, ("option long value=%lu", value));
1336    return value;    return value;
1337  }                              }                            
   
 /**  
  * Find the DHCP client attached to a network interface.  
  *  
  * Given an network interface, return the corresponding dhcp state  
  * or NULL if the interface was not under DHCP control.  
  */  
 struct dhcp_state *dhcp_find_client(struct netif *netif)  
 {  
   struct dhcp_state *state = NULL;  
   struct dhcp_state *list_state = client_list;  
   
   DEBUGF(DHCP_DEBUG, ("dhcp_find_client()"));  
   while ((state == NULL) && (list_state != NULL))  
   {  
      DEBUGF(DHCP_DEBUG, ("dhcp_find_client(): checking state %p", list_state));  
     // this interface already has a DHCP client attached  
     if (list_state->netif == netif)  
     {  
       state = list_state;  
        DEBUGF(DHCP_DEBUG, ("dhcp_find_client(): interface already under DHCP control"));  
     }  
     if (list_state->next != NULL)  
     {      
       // select the next client state  
       list_state = list_state->next;  
     }  
     // reached end of list  
     else  
     {  
        DEBUGF(DHCP_DEBUG, ("dhcp_find_client(): end of list reached"));  
       break;  
       // { state == NULL }  
       // { list_state is last item in list }  
     }  
   }  
   return state;  
 }  

Legend:
Removed from v.1.11.2.2  
changed lines
  Added in v.1.11.2.3

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26