Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / geekos / src / lwip / core / dhcp.c
1 /**
2  * @file
3  * Dynamic Host Configuration Protocol client
4  *
5  */
6
7 /*
8  *
9  * Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@gmx.net>
10  * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
11  * All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without modification,
14  * are permitted provided that the following conditions are met:
15  *
16  * 1. Redistributions of source code must retain the above copyright notice,
17  *    this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright notice,
19  *    this list of conditions and the following disclaimer in the documentation
20  *    and/or other materials provided with the distribution.
21  * 3. The name of the author may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
25  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
27  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
29  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33  * OF SUCH DAMAGE.
34  *
35  * This file is a contribution to the lwIP TCP/IP stack.
36  * The Swedish Institute of Computer Science and Adam Dunkels
37  * are specifically granted permission to redistribute this
38  * source code.
39  *
40  * Author: Leon Woestenberg <leon.woestenberg@gmx.net>
41  *
42  * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform
43  * with RFC 2131 and RFC 2132.
44  *
45  * TODO:
46  * - Proper parsing of DHCP messages exploiting file/sname field overloading.
47  * - Add JavaDoc style documentation (API, internals).
48  * - Support for interfaces other than Ethernet (SLIP, PPP, ...)
49  *
50  * Please coordinate changes and requests with Leon Woestenberg
51  * <leon.woestenberg@gmx.net>
52  *
53  * Integration with your code:
54  *
55  * In lwip/dhcp.h
56  * #define DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute)
57  * #define DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer)
58  *
59  * Then have your application call dhcp_coarse_tmr() and
60  * dhcp_fine_tmr() on the defined intervals.
61  *
62  * dhcp_start(struct netif *netif);
63  * starts a DHCP client instance which configures the interface by
64  * obtaining an IP address lease and maintaining it.
65  *
66  * Use dhcp_release(netif) to end the lease and use dhcp_stop(netif)
67  * to remove the DHCP client.
68  *
69  */
70
71 #include "lwip/opt.h"
72
73 #if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */
74
75 #include "lwip/stats.h"
76 #include "lwip/mem.h"
77 #include "lwip/udp.h"
78 #include "lwip/ip_addr.h"
79 #include "lwip/netif.h"
80 #include "lwip/inet.h"
81 #include "lwip/sys.h"
82 #include "lwip/dhcp.h"
83 #include "lwip/autoip.h"
84 #include "lwip/dns.h"
85 #include "netif/etharp.h"
86
87 #include <string.h>
88
89 /** global transaction identifier, must be
90  *  unique for each DHCP request. We simply increment, starting
91  *  with this value (easy to match with a packet analyzer) */
92 static u32_t xid = 0xABCD0000;
93
94 /* DHCP client state machine functions */
95 static void dhcp_handle_ack(struct netif *netif);
96 static void dhcp_handle_nak(struct netif *netif);
97 static void dhcp_handle_offer(struct netif *netif);
98
99 static err_t dhcp_discover(struct netif *netif);
100 static err_t dhcp_select(struct netif *netif);
101 static void dhcp_check(struct netif *netif);
102 static void dhcp_bind(struct netif *netif);
103 #if DHCP_DOES_ARP_CHECK
104 static err_t dhcp_decline(struct netif *netif);
105 #endif /* DHCP_DOES_ARP_CHECK */
106 static err_t dhcp_rebind(struct netif *netif);
107 static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
108
109 /* receive, unfold, parse and free incoming messages */
110 static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
111 static err_t dhcp_unfold_reply(struct dhcp *dhcp);
112 static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type);
113 static u8_t dhcp_get_option_byte(u8_t *ptr);
114 #if 0
115 static u16_t dhcp_get_option_short(u8_t *ptr);
116 #endif
117 static u32_t dhcp_get_option_long(u8_t *ptr);
118 static void dhcp_free_reply(struct dhcp *dhcp);
119
120 /* set the DHCP timers */
121 static void dhcp_timeout(struct netif *netif);
122 static void dhcp_t1_timeout(struct netif *netif);
123 static void dhcp_t2_timeout(struct netif *netif);
124
125 /* build outgoing messages */
126 /* create a DHCP request, fill in common headers */
127 static err_t dhcp_create_request(struct netif *netif);
128 /* free a DHCP request */
129 static void dhcp_delete_request(struct netif *netif);
130 /* add a DHCP option (type, then length in bytes) */
131 static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len);
132 /* add option values */
133 static void dhcp_option_byte(struct dhcp *dhcp, u8_t value);
134 static void dhcp_option_short(struct dhcp *dhcp, u16_t value);
135 static void dhcp_option_long(struct dhcp *dhcp, u32_t value);
136 /* always add the DHCP options trailer to end and pad */
137 static void dhcp_option_trailer(struct dhcp *dhcp);
138
139 /**
140  * Back-off the DHCP client (because of a received NAK response).
141  *
142  * Back-off the DHCP client because of a received NAK. Receiving a
143  * NAK means the client asked for something non-sensible, for
144  * example when it tries to renew a lease obtained on another network.
145  *
146  * We clear any existing set IP address and restart DHCP negotiation
147  * afresh (as per RFC2131 3.2.3).
148  *
149  * @param netif the netif under DHCP control
150  */
151 static void
152 dhcp_handle_nak(struct netif *netif)
153 {
154   struct dhcp *dhcp = netif->dhcp;
155   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n", 
156     (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
157   /* Set the interface down since the address must no longer be used, as per RFC2131 */
158   netif_set_down(netif);
159   /* remove IP address from interface */
160   netif_set_ipaddr(netif, IP_ADDR_ANY);
161   netif_set_gw(netif, IP_ADDR_ANY);
162   netif_set_netmask(netif, IP_ADDR_ANY); 
163   /* Change to a defined state */
164   dhcp_set_state(dhcp, DHCP_BACKING_OFF);
165   /* We can immediately restart discovery */
166   dhcp_discover(netif);
167 }
168
169 /**
170  * Checks if the offered IP address is already in use.
171  *
172  * It does so by sending an ARP request for the offered address and
173  * entering CHECKING state. If no ARP reply is received within a small
174  * interval, the address is assumed to be free for use by us.
175  *
176  * @param netif the netif under DHCP control
177  */
178 static void
179 dhcp_check(struct netif *netif)
180 {
181   struct dhcp *dhcp = netif->dhcp;
182   err_t result;
183   u16_t msecs;
184   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
185     (s16_t)netif->name[1]));
186   /* create an ARP query for the offered IP address, expecting that no host
187      responds, as the IP address should not be in use. */
188   result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
189   if (result != ERR_OK) {
190     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_check: could not perform ARP query\n"));
191   }
192   dhcp->tries++;
193   msecs = 500;
194   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
195   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs));
196   dhcp_set_state(dhcp, DHCP_CHECKING);
197 }
198
199 /**
200  * Remember the configuration offered by a DHCP server.
201  *
202  * @param netif the netif under DHCP control
203  */
204 static void
205 dhcp_handle_offer(struct netif *netif)
206 {
207   struct dhcp *dhcp = netif->dhcp;
208   /* obtain the server address */
209   u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID);
210   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
211     (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
212   if (option_ptr != NULL) {
213     dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
214     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", dhcp->server_ip_addr.addr));
215     /* remember offered address */
216     ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr);
217     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr));
218
219     dhcp_select(netif);
220   }
221 }
222
223 /**
224  * Select a DHCP server offer out of all offers.
225  *
226  * Simply select the first offer received.
227  *
228  * @param netif the netif under DHCP control
229  * @return lwIP specific error (see error.h)
230  */
231 static err_t
232 dhcp_select(struct netif *netif)
233 {
234   struct dhcp *dhcp = netif->dhcp;
235   err_t result;
236   u16_t msecs;
237 #if LWIP_NETIF_HOSTNAME
238   const char *p;
239 #endif /* LWIP_NETIF_HOSTNAME */
240
241   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
242
243   /* create and initialize the DHCP message header */
244   result = dhcp_create_request(netif);
245   if (result == ERR_OK) {
246     dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
247     dhcp_option_byte(dhcp, DHCP_REQUEST);
248
249     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
250     dhcp_option_short(dhcp, 576);
251
252     /* MUST request the offered IP address */
253     dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
254     dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
255
256     dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
257     dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
258
259     dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
260     dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
261     dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
262     dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
263     dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
264
265 #if LWIP_NETIF_HOSTNAME
266     p = (const char*)netif->hostname;
267     if (p!=NULL) {
268       dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, strlen(p));
269       while (*p) {
270         dhcp_option_byte(dhcp, *p++);
271       }
272     }
273 #endif /* LWIP_NETIF_HOSTNAME */
274
275     dhcp_option_trailer(dhcp);
276     /* shrink the pbuf to the actual content length */
277     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
278
279     /* TODO: we really should bind to a specific local interface here
280        but we cannot specify an unconfigured netif as it is addressless */
281     /* send broadcast to any DHCP server */
282     udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
283     /* reconnect to any (or to server here?!) */
284     udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
285     dhcp_delete_request(netif);
286     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n"));
287     dhcp_set_state(dhcp, DHCP_REQUESTING);
288   } else {
289     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_select: could not allocate DHCP request\n"));
290   }
291   dhcp->tries++;
292   msecs = dhcp->tries < 4 ? dhcp->tries * 1000 : 4 * 1000;
293   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
294   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs));
295   return result;
296 }
297
298 /**
299  * The DHCP timer that checks for lease renewal/rebind timeouts.
300  *
301  */
302 void
303 dhcp_coarse_tmr()
304 {
305   struct netif *netif = netif_list;
306   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n"));
307   /* iterate through all network interfaces */
308   while (netif != NULL) {
309     /* only act on DHCP configured interfaces */
310     if (netif->dhcp != NULL) {
311       /* timer is active (non zero), and triggers (zeroes) now? */
312       if (netif->dhcp->t2_timeout-- == 1) {
313         LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n"));
314         /* this clients' rebind timeout triggered */
315         dhcp_t2_timeout(netif);
316       /* timer is active (non zero), and triggers (zeroes) now */
317       } else if (netif->dhcp->t1_timeout-- == 1) {
318         LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n"));
319         /* this clients' renewal timeout triggered */
320         dhcp_t1_timeout(netif);
321       }
322     }
323     /* proceed to next netif */
324     netif = netif->next;
325   }
326 }
327
328 /**
329  * DHCP transaction timeout handling
330  *
331  * A DHCP server is expected to respond within a short period of time.
332  * This timer checks whether an outstanding DHCP request is timed out.
333  * 
334  */
335 void
336 dhcp_fine_tmr()
337 {
338   struct netif *netif = netif_list;
339   /* loop through netif's */
340   while (netif != NULL) {
341     /* only act on DHCP configured interfaces */
342     if (netif->dhcp != NULL) {
343       /* timer is active (non zero), and is about to trigger now */      
344       if (netif->dhcp->request_timeout > 1) {
345         netif->dhcp->request_timeout--;
346       }
347       else if (netif->dhcp->request_timeout == 1) {
348         netif->dhcp->request_timeout--;
349         /* { netif->dhcp->request_timeout == 0 } */
350         LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
351         /* this clients' request timeout triggered */
352         dhcp_timeout(netif);
353       }
354     }
355     /* proceed to next network interface */
356     netif = netif->next;
357   }
358 }
359
360 /**
361  * A DHCP negotiation transaction, or ARP request, has timed out.
362  *
363  * The timer that was started with the DHCP or ARP request has
364  * timed out, indicating no response was received in time.
365  *
366  * @param netif the netif under DHCP control
367  */
368 static void
369 dhcp_timeout(struct netif *netif)
370 {
371   struct dhcp *dhcp = netif->dhcp;
372   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_timeout()\n"));
373   /* back-off period has passed, or server selection timed out */
374   if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) {
375     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n"));
376     dhcp_discover(netif);
377   /* receiving the requested lease timed out */
378   } else if (dhcp->state == DHCP_REQUESTING) {
379     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n"));
380     if (dhcp->tries <= 5) {
381       dhcp_select(netif);
382     } else {
383       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n"));
384       dhcp_release(netif);
385       dhcp_discover(netif);
386     }
387   /* received no ARP reply for the offered address (which is good) */
388   } else if (dhcp->state == DHCP_CHECKING) {
389     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n"));
390     if (dhcp->tries <= 1) {
391       dhcp_check(netif);
392     /* no ARP replies on the offered address,
393        looks like the IP address is indeed free */
394     } else {
395       /* bind the interface to the offered address */
396       dhcp_bind(netif);
397     }
398   }
399   /* did not get response to renew request? */
400   else if (dhcp->state == DHCP_RENEWING) {
401     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RENEWING, DHCP request timed out\n"));
402     /* just retry renewal */
403     /* note that the rebind timer will eventually time-out if renew does not work */
404     dhcp_renew(netif);
405   /* did not get response to rebind request? */
406   } else if (dhcp->state == DHCP_REBINDING) {
407     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REBINDING, DHCP request timed out\n"));
408     if (dhcp->tries <= 8) {
409       dhcp_rebind(netif);
410     } else {
411       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RELEASING, DISCOVERING\n"));
412       dhcp_release(netif);
413       dhcp_discover(netif);
414     }
415   }
416 }
417
418 /**
419  * The renewal period has timed out.
420  *
421  * @param netif the netif under DHCP control
422  */
423 static void
424 dhcp_t1_timeout(struct netif *netif)
425 {
426   struct dhcp *dhcp = netif->dhcp;
427   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n"));
428   if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
429     /* just retry to renew - note that the rebind timer (t2) will
430      * eventually time-out if renew tries fail. */
431     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t1_timeout(): must renew\n"));
432     dhcp_renew(netif);
433   }
434 }
435
436 /**
437  * The rebind period has timed out.
438  *
439  * @param netif the netif under DHCP control
440  */
441 static void
442 dhcp_t2_timeout(struct netif *netif)
443 {
444   struct dhcp *dhcp = netif->dhcp;
445   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n"));
446   if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
447     /* just retry to rebind */
448     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout(): must rebind\n"));
449     dhcp_rebind(netif);
450   }
451 }
452
453 /**
454  * Handle a DHCP ACK packet
455  *
456  * @param netif the netif under DHCP control
457  */
458 static void
459 dhcp_handle_ack(struct netif *netif)
460 {
461   struct dhcp *dhcp = netif->dhcp;
462   u8_t *option_ptr;
463   /* clear options we might not get from the ACK */
464   dhcp->offered_sn_mask.addr = 0;
465   dhcp->offered_gw_addr.addr = 0;
466   dhcp->offered_bc_addr.addr = 0;
467
468   /* lease time given? */
469   option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_LEASE_TIME);
470   if (option_ptr != NULL) {
471     /* remember offered lease time */
472     dhcp->offered_t0_lease = dhcp_get_option_long(option_ptr + 2);
473   }
474   /* renewal period given? */
475   option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T1);
476   if (option_ptr != NULL) {
477     /* remember given renewal period */
478     dhcp->offered_t1_renew = dhcp_get_option_long(option_ptr + 2);
479   } else {
480     /* calculate safe periods for renewal */
481     dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2;
482   }
483
484   /* renewal period given? */
485   option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T2);
486   if (option_ptr != NULL) {
487     /* remember given rebind period */
488     dhcp->offered_t2_rebind = dhcp_get_option_long(option_ptr + 2);
489   } else {
490     /* calculate safe periods for rebinding */
491     dhcp->offered_t2_rebind = dhcp->offered_t0_lease;
492   }
493
494   /* (y)our internet address */
495   ip_addr_set(&dhcp->offered_ip_addr, &dhcp->msg_in->yiaddr);
496
497 /**
498  * Patch #1308
499  * TODO: we must check if the file field is not overloaded by DHCP options!
500  */
501 #if 0
502   /* boot server address */
503   ip_addr_set(&dhcp->offered_si_addr, &dhcp->msg_in->siaddr);
504   /* boot file name */
505   if (dhcp->msg_in->file[0]) {
506     dhcp->boot_file_name = mem_malloc(strlen(dhcp->msg_in->file) + 1);
507     strcpy(dhcp->boot_file_name, dhcp->msg_in->file);
508   }
509 #endif
510
511   /* subnet mask */
512   option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SUBNET_MASK);
513   /* subnet mask given? */
514   if (option_ptr != NULL) {
515     dhcp->offered_sn_mask.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
516   }
517
518   /* gateway router */
519   option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_ROUTER);
520   if (option_ptr != NULL) {
521     dhcp->offered_gw_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
522   }
523
524   /* broadcast address */
525   option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_BROADCAST);
526   if (option_ptr != NULL) {
527     dhcp->offered_bc_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
528   }
529   
530   /* DNS servers */
531   option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_DNS_SERVER);
532   if (option_ptr != NULL) {
533     u8_t n;
534     dhcp->dns_count = dhcp_get_option_byte(&option_ptr[1]) / (u32_t)sizeof(struct ip_addr);
535     /* limit to at most DHCP_MAX_DNS DNS servers */
536     if (dhcp->dns_count > DHCP_MAX_DNS)
537       dhcp->dns_count = DHCP_MAX_DNS;
538     for (n = 0; n < dhcp->dns_count; n++) {
539       dhcp->offered_dns_addr[n].addr = htonl(dhcp_get_option_long(&option_ptr[2 + n * 4]));
540 #if LWIP_DNS
541       dns_setserver( n, (struct ip_addr *)(&(dhcp->offered_dns_addr[n].addr)));
542 #endif /* LWIP_DNS */
543     }
544 #if LWIP_DNS
545     dns_setserver( n, (struct ip_addr *)(&ip_addr_any));
546 #endif /* LWIP_DNS */
547   }
548 }
549
550 /**
551  * Start DHCP negotiation for a network interface.
552  *
553  * If no DHCP client instance was attached to this interface,
554  * a new client is created first. If a DHCP client instance
555  * was already present, it restarts negotiation.
556  *
557  * @param netif The lwIP network interface
558  * @return lwIP error code
559  * - ERR_OK - No error
560  * - ERR_MEM - Out of memory
561  */
562 err_t
563 dhcp_start(struct netif *netif)
564 {
565   struct dhcp *dhcp;
566   err_t result = ERR_OK;
567
568   LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
569   dhcp = netif->dhcp;
570   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
571   netif->flags &= ~NETIF_FLAG_DHCP;
572
573   /* no DHCP client attached yet? */
574   if (dhcp == NULL) {
575     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
576     dhcp = mem_malloc(sizeof(struct dhcp));
577     if (dhcp == NULL) {
578       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
579       return ERR_MEM;
580     }
581     /* store this dhcp client in the netif */
582     netif->dhcp = dhcp;
583     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp"));
584   /* already has DHCP client attached */
585   } else {
586     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("dhcp_start(): restarting DHCP configuration\n"));
587   }
588     
589   /* clear data structure */
590   memset(dhcp, 0, sizeof(struct dhcp));
591   /* allocate UDP PCB */
592   dhcp->pcb = udp_new();
593   if (dhcp->pcb == NULL) {
594     LWIP_DEBUGF(DHCP_DEBUG  | LWIP_DBG_TRACE, ("dhcp_start(): could not obtain pcb\n"));
595     mem_free((void *)dhcp);
596     netif->dhcp = dhcp = NULL;
597     return ERR_MEM;
598   }
599   /* set up local and remote port for the pcb */
600   udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
601   udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
602   /* set up the recv callback and argument */
603   udp_recv(dhcp->pcb, dhcp_recv, netif);
604   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
605   /* (re)start the DHCP negotiation */
606   result = dhcp_discover(netif);
607   if (result != ERR_OK) {
608     /* free resources allocated above */
609     dhcp_stop(netif);
610     return ERR_MEM;
611   }
612   netif->flags |= NETIF_FLAG_DHCP;
613   return result;
614 }
615
616 /**
617  * Inform a DHCP server of our manual configuration.
618  *
619  * This informs DHCP servers of our fixed IP address configuration
620  * by sending an INFORM message. It does not involve DHCP address
621  * configuration, it is just here to be nice to the network.
622  *
623  * @param netif The lwIP network interface
624  */
625 void
626 dhcp_inform(struct netif *netif)
627 {
628   struct dhcp *dhcp, *old_dhcp = netif->dhcp;
629   err_t result = ERR_OK;
630   dhcp = mem_malloc(sizeof(struct dhcp));
631   if (dhcp == NULL) {
632     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_inform(): could not allocate dhcp\n"));
633     return;
634   }
635   netif->dhcp = dhcp;
636   memset(dhcp, 0, sizeof(struct dhcp));
637
638   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): allocated dhcp\n"));
639   dhcp->pcb = udp_new();
640   if (dhcp->pcb == NULL) {
641     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_inform(): could not obtain pcb"));
642     mem_free((void *)dhcp);
643     return;
644   }
645   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n"));
646   /* create and initialize the DHCP message header */
647   result = dhcp_create_request(netif);
648   if (result == ERR_OK) {
649
650     dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
651     dhcp_option_byte(dhcp, DHCP_INFORM);
652
653     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
654     /* TODO: use netif->mtu ?! */
655     dhcp_option_short(dhcp, 576);
656
657     dhcp_option_trailer(dhcp);
658
659     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
660
661     udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
662     udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
663     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n"));
664     udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
665     udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
666     dhcp_delete_request(netif);
667   } else {
668     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_inform: could not allocate DHCP request\n"));
669   }
670
671   if (dhcp != NULL) {
672     if (dhcp->pcb != NULL) {
673       udp_remove(dhcp->pcb);
674     }
675     dhcp->pcb = NULL;
676     mem_free((void *)dhcp);
677     netif->dhcp = old_dhcp;
678   }
679 }
680
681 #if DHCP_DOES_ARP_CHECK
682 /**
683  * Match an ARP reply with the offered IP address.
684  *
685  * @param netif the network interface on which the reply was received
686  * @param addr The IP address we received a reply from
687  */
688 void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
689 {
690   LWIP_ERROR("netif != NULL", (netif != NULL), return;);
691   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_arp_reply()\n"));
692   /* is a DHCP client doing an ARP check? */
693   if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
694     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", addr->addr));
695     /* did a host respond with the address we
696        were offered by the DHCP server? */
697     if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
698       /* we will not accept the offered address */
699       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1, ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
700       dhcp_decline(netif);
701     }
702   }
703 }
704
705 /**
706  * Decline an offered lease.
707  *
708  * Tell the DHCP server we do not accept the offered address.
709  * One reason to decline the lease is when we find out the address
710  * is already in use by another host (through ARP).
711  *
712  * @param netif the netif under DHCP control
713  */
714 static err_t
715 dhcp_decline(struct netif *netif)
716 {
717   struct dhcp *dhcp = netif->dhcp;
718   err_t result = ERR_OK;
719   u16_t msecs;
720   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_decline()\n"));
721   dhcp_set_state(dhcp, DHCP_BACKING_OFF);
722   /* create and initialize the DHCP message header */
723   result = dhcp_create_request(netif);
724   if (result == ERR_OK) {
725     dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
726     dhcp_option_byte(dhcp, DHCP_DECLINE);
727
728     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
729     dhcp_option_short(dhcp, 576);
730
731     dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
732     dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
733
734     dhcp_option_trailer(dhcp);
735     /* resize pbuf to reflect true size of options */
736     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
737
738     /* @todo: should we really connect here? we are performing sendto() */
739     udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
740     /* per section 4.4.4, broadcast DECLINE messages */
741     udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
742     dhcp_delete_request(netif);
743     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
744   } else {
745     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_decline: could not allocate DHCP request\n"));
746   }
747   dhcp->tries++;
748   msecs = 10*1000;
749   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
750   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs));
751   return result;
752 }
753 #endif
754
755
756 /**
757  * Start the DHCP process, discover a DHCP server.
758  *
759  * @param netif the netif under DHCP control
760  */
761 static err_t
762 dhcp_discover(struct netif *netif)
763 {
764   struct dhcp *dhcp = netif->dhcp;
765   err_t result = ERR_OK;
766   u16_t msecs;
767   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_discover()\n"));
768   ip_addr_set(&dhcp->offered_ip_addr, IP_ADDR_ANY);
769   /* create and initialize the DHCP message header */
770   result = dhcp_create_request(netif);
771   if (result == ERR_OK) {
772     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n"));
773     dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
774     dhcp_option_byte(dhcp, DHCP_DISCOVER);
775
776     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
777     dhcp_option_short(dhcp, 576);
778
779     dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
780     dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
781     dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
782     dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
783     dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
784
785     dhcp_option_trailer(dhcp);
786
787     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n"));
788     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
789
790     udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
791     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
792     udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
793     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
794     dhcp_delete_request(netif);
795     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
796     dhcp_set_state(dhcp, DHCP_SELECTING);
797   } else {
798     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_discover: could not allocate DHCP request\n"));
799   }
800   dhcp->tries++;
801 #if LWIP_DHCP_AUTOIP_COOP
802   /* that means we waited 57 seconds */
803   if(dhcp->tries >= 9 && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) {
804     dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON;
805     autoip_start(netif);
806   }
807 #endif /* LWIP_DHCP_AUTOIP_COOP */
808   msecs = dhcp->tries < 4 ? (dhcp->tries + 1) * 1000 : 10 * 1000;
809   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
810   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs));
811   return result;
812 }
813
814
815 /**
816  * Bind the interface to the offered IP address.
817  *
818  * @param netif network interface to bind to the offered address
819  */
820 static void
821 dhcp_bind(struct netif *netif)
822 {
823   u32_t timeout;
824   struct dhcp *dhcp;
825   struct ip_addr sn_mask, gw_addr;
826   LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;);
827   dhcp = netif->dhcp;
828   LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;);
829   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
830
831   /* temporary DHCP lease? */
832   if (dhcp->offered_t1_renew != 0xffffffffUL) {
833     /* set renewal period timer */
834     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew));
835     timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
836     if(timeout > 0xffff) {
837       timeout = 0xffff;
838     }
839     dhcp->t1_timeout = (u16_t)timeout;
840     if (dhcp->t1_timeout == 0) {
841       dhcp->t1_timeout = 1;
842     }
843     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000));
844   }
845   /* set renewal period timer */
846   if (dhcp->offered_t2_rebind != 0xffffffffUL) {
847     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind));
848     timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
849     if(timeout > 0xffff) {
850       timeout = 0xffff;
851     }
852     dhcp->t2_timeout = (u16_t)timeout;
853     if (dhcp->t2_timeout == 0) {
854       dhcp->t2_timeout = 1;
855     }
856     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000));
857   }
858   /* copy offered network mask */
859   ip_addr_set(&sn_mask, &dhcp->offered_sn_mask);
860
861   /* subnet mask not given? */
862   /* TODO: this is not a valid check. what if the network mask is 0? */
863   if (sn_mask.addr == 0) {
864     /* choose a safe subnet mask given the network class */
865     u8_t first_octet = ip4_addr1(&sn_mask);
866     if (first_octet <= 127) {
867       sn_mask.addr = htonl(0xff000000);
868     } else if (first_octet >= 192) {
869       sn_mask.addr = htonl(0xffffff00);
870     } else {
871       sn_mask.addr = htonl(0xffff0000);
872     }
873   }
874
875   ip_addr_set(&gw_addr, &dhcp->offered_gw_addr);
876   /* gateway address not given? */
877   if (gw_addr.addr == 0) {
878     /* copy network address */
879     gw_addr.addr = (dhcp->offered_ip_addr.addr & sn_mask.addr);
880     /* use first host address on network as gateway */
881     gw_addr.addr |= htonl(0x00000001);
882   }
883
884   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr));
885   netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
886   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n", sn_mask.addr));
887   netif_set_netmask(netif, &sn_mask);
888   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n", gw_addr.addr));
889   netif_set_gw(netif, &gw_addr);
890   /* bring the interface up */
891   netif_set_up(netif);
892   /* netif is now bound to DHCP leased address */
893   dhcp_set_state(dhcp, DHCP_BOUND);
894 }
895
896 /**
897  * Renew an existing DHCP lease at the involved DHCP server.
898  *
899  * @param netif network interface which must renew its lease
900  */
901 err_t
902 dhcp_renew(struct netif *netif)
903 {
904   struct dhcp *dhcp = netif->dhcp;
905   err_t result;
906   u16_t msecs;
907   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_renew()\n"));
908   dhcp_set_state(dhcp, DHCP_RENEWING);
909
910   /* create and initialize the DHCP message header */
911   result = dhcp_create_request(netif);
912   if (result == ERR_OK) {
913
914     dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
915     dhcp_option_byte(dhcp, DHCP_REQUEST);
916
917     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
918     /* TODO: use netif->mtu in some way */
919     dhcp_option_short(dhcp, 576);
920
921 #if 0
922     dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
923     dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
924 #endif
925
926 #if 0
927     dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
928     dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
929 #endif
930     /* append DHCP message trailer */
931     dhcp_option_trailer(dhcp);
932
933     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
934
935     udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
936     udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
937     dhcp_delete_request(netif);
938
939     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n"));
940   } else {
941     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_renew: could not allocate DHCP request\n"));
942   }
943   dhcp->tries++;
944   /* back-off on retries, but to a maximum of 20 seconds */
945   msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
946   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
947   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs));
948   return result;
949 }
950
951 /**
952  * Rebind with a DHCP server for an existing DHCP lease.
953  *
954  * @param netif network interface which must rebind with a DHCP server
955  */
956 static err_t
957 dhcp_rebind(struct netif *netif)
958 {
959   struct dhcp *dhcp = netif->dhcp;
960   err_t result;
961   u16_t msecs;
962   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n"));
963   dhcp_set_state(dhcp, DHCP_REBINDING);
964
965   /* create and initialize the DHCP message header */
966   result = dhcp_create_request(netif);
967   if (result == ERR_OK) {
968
969     dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
970     dhcp_option_byte(dhcp, DHCP_REQUEST);
971
972     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
973     dhcp_option_short(dhcp, 576);
974
975 #if 0
976     dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
977     dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
978
979     dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
980     dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
981 #endif
982
983     dhcp_option_trailer(dhcp);
984
985     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
986
987     /* broadcast to server */
988     udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
989     udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
990     dhcp_delete_request(netif);
991     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n"));
992   } else {
993     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_rebind: could not allocate DHCP request\n"));
994   }
995   dhcp->tries++;
996   msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
997   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
998   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs));
999   return result;
1000 }
1001
1002 /**
1003  * Release a DHCP lease.
1004  *
1005  * @param netif network interface which must release its lease
1006  */
1007 err_t
1008 dhcp_release(struct netif *netif)
1009 {
1010   struct dhcp *dhcp = netif->dhcp;
1011   err_t result;
1012   u16_t msecs;
1013   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_release()\n"));
1014
1015   /* idle DHCP client */
1016   dhcp_set_state(dhcp, DHCP_OFF);
1017   /* clean old DHCP offer */
1018   dhcp->server_ip_addr.addr = 0;
1019   dhcp->offered_ip_addr.addr = dhcp->offered_sn_mask.addr = 0;
1020   dhcp->offered_gw_addr.addr = dhcp->offered_bc_addr.addr = 0;
1021   dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0;
1022   dhcp->dns_count = 0;
1023   
1024   /* create and initialize the DHCP message header */
1025   result = dhcp_create_request(netif);
1026   if (result == ERR_OK) {
1027     dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
1028     dhcp_option_byte(dhcp, DHCP_RELEASE);
1029
1030     dhcp_option_trailer(dhcp);
1031
1032     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
1033
1034     udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
1035     udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
1036     dhcp_delete_request(netif);
1037     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n"));
1038   } else {
1039     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_release: could not allocate DHCP request\n"));
1040   }
1041   dhcp->tries++;
1042   msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
1043   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
1044   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs));
1045   /* bring the interface down */
1046   netif_set_down(netif);
1047   /* remove IP address from interface */
1048   netif_set_ipaddr(netif, IP_ADDR_ANY);
1049   netif_set_gw(netif, IP_ADDR_ANY);
1050   netif_set_netmask(netif, IP_ADDR_ANY);
1051   
1052   /* TODO: netif_down(netif); */
1053   return result;
1054 }
1055
1056 /**
1057  * Remove the DHCP client from the interface.
1058  *
1059  * @param netif The network interface to stop DHCP on
1060  */
1061 void
1062 dhcp_stop(struct netif *netif)
1063 {
1064   struct dhcp *dhcp = netif->dhcp;
1065   LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;);
1066
1067   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_stop()\n"));
1068   /* netif is DHCP configured? */
1069   if (dhcp != NULL) {
1070     if (dhcp->pcb != NULL) {
1071       udp_remove(dhcp->pcb);
1072       dhcp->pcb = NULL;
1073     }
1074     if (dhcp->p != NULL) {
1075       pbuf_free(dhcp->p);
1076       dhcp->p = NULL;
1077     }
1078     /* free unfolded reply */
1079     dhcp_free_reply(dhcp);
1080     mem_free((void *)dhcp);
1081     netif->dhcp = NULL;
1082   }
1083 }
1084
1085 /*
1086  * Set the DHCP state of a DHCP client.
1087  *
1088  * If the state changed, reset the number of tries.
1089  *
1090  * TODO: we might also want to reset the timeout here?
1091  */
1092 static void
1093 dhcp_set_state(struct dhcp *dhcp, u8_t new_state)
1094 {
1095   if (new_state != dhcp->state) {
1096     dhcp->state = new_state;
1097     dhcp->tries = 0;
1098   }
1099 }
1100
1101 /*
1102  * Concatenate an option type and length field to the outgoing
1103  * DHCP message.
1104  *
1105  */
1106 static void
1107 dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len)
1108 {
1109   LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN);
1110   dhcp->msg_out->options[dhcp->options_out_len++] = option_type;
1111   dhcp->msg_out->options[dhcp->options_out_len++] = option_len;
1112 }
1113 /*
1114  * Concatenate a single byte to the outgoing DHCP message.
1115  *
1116  */
1117 static void
1118 dhcp_option_byte(struct dhcp *dhcp, u8_t value)
1119 {
1120   LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN);
1121   dhcp->msg_out->options[dhcp->options_out_len++] = value;
1122 }
1123
1124 static void
1125 dhcp_option_short(struct dhcp *dhcp, u16_t value)
1126 {
1127   LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN);
1128   dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8);
1129   dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU);
1130 }
1131
1132 static void
1133 dhcp_option_long(struct dhcp *dhcp, u32_t value)
1134 {
1135   LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN);
1136   dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24);
1137   dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16);
1138   dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8);
1139   dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL));
1140 }
1141
1142 /**
1143  * Extract the DHCP message and the DHCP options.
1144  *
1145  * Extract the DHCP message and the DHCP options, each into a contiguous
1146  * piece of memory. As a DHCP message is variable sized by its options,
1147  * and also allows overriding some fields for options, the easy approach
1148  * is to first unfold the options into a conitguous piece of memory, and
1149  * use that further on.
1150  *
1151  */
1152 static err_t
1153 dhcp_unfold_reply(struct dhcp *dhcp)
1154 {
1155   u16_t ret;
1156   LWIP_ERROR("dhcp != NULL", (dhcp != NULL), return ERR_ARG;);
1157   LWIP_ERROR("dhcp->p != NULL", (dhcp->p != NULL), return ERR_VAL;);
1158   /* free any left-overs from previous unfolds */
1159   dhcp_free_reply(dhcp);
1160   /* options present? */
1161   if (dhcp->p->tot_len > (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN)) {
1162     dhcp->options_in_len = dhcp->p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
1163     dhcp->options_in = mem_malloc(dhcp->options_in_len);
1164     if (dhcp->options_in == NULL) {
1165       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_unfold_reply(): could not allocate dhcp->options\n"));
1166       return ERR_MEM;
1167     }
1168   }
1169   dhcp->msg_in = mem_malloc(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
1170   if (dhcp->msg_in == NULL) {
1171     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_unfold_reply(): could not allocate dhcp->msg_in\n"));
1172     mem_free((void *)dhcp->options_in);
1173     dhcp->options_in = NULL;
1174     return ERR_MEM;
1175   }
1176
1177   /** copy the DHCP message without options */
1178   ret = pbuf_copy_partial(dhcp->p, dhcp->msg_in, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN, 0);
1179   LWIP_ASSERT("ret == sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN", ret == sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
1180   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes into dhcp->msg_in[]\n",
1181      sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN));
1182
1183   if (dhcp->options_in != NULL) {
1184     /** copy the DHCP options */
1185     ret = pbuf_copy_partial(dhcp->p, dhcp->options_in, dhcp->options_in_len, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
1186     LWIP_ASSERT("ret == dhcp->options_in_len", ret == dhcp->options_in_len);
1187     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes to dhcp->options_in[]\n",
1188       dhcp->options_in_len));
1189   }
1190   LWIP_UNUSED_ARG(ret);
1191   return ERR_OK;
1192 }
1193
1194 /**
1195  * Free the incoming DHCP message including contiguous copy of
1196  * its DHCP options.
1197  *
1198  */
1199 static void dhcp_free_reply(struct dhcp *dhcp)
1200 {
1201   if (dhcp->msg_in != NULL) {
1202     mem_free((void *)dhcp->msg_in);
1203     dhcp->msg_in = NULL;
1204   }
1205   if (dhcp->options_in) {
1206     mem_free((void *)dhcp->options_in);
1207     dhcp->options_in = NULL;
1208     dhcp->options_in_len = 0;
1209   }
1210   LWIP_DEBUGF(DHCP_DEBUG, ("dhcp_free_reply(): free'd\n"));
1211 }
1212
1213
1214 /**
1215  * If an incoming DHCP message is in response to us, then trigger the state machine
1216  */
1217 static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
1218 {
1219   struct netif *netif = (struct netif *)arg;
1220   struct dhcp *dhcp = netif->dhcp;
1221   struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload;
1222   u8_t *options_ptr;
1223   u8_t msg_type;
1224   u8_t i;
1225   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p,
1226     (u16_t)(ntohl(addr->addr) >> 24 & 0xff), (u16_t)(ntohl(addr->addr) >> 16 & 0xff),
1227     (u16_t)(ntohl(addr->addr) >>  8 & 0xff), (u16_t)(ntohl(addr->addr) & 0xff), port));
1228   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
1229   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len));
1230   /* prevent warnings about unused arguments */
1231   LWIP_UNUSED_ARG(pcb);
1232   LWIP_UNUSED_ARG(addr);
1233   LWIP_UNUSED_ARG(port);
1234   dhcp->p = p;
1235   /* TODO: check packet length before reading them */
1236   if (reply_msg->op != DHCP_BOOTREPLY) {
1237     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op));
1238     goto free_pbuf_and_return;
1239   }
1240   /* iterate through hardware address and match against DHCP message */
1241   for (i = 0; i < netif->hwaddr_len; i++) {
1242     if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
1243       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
1244         (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i]));
1245       goto free_pbuf_and_return;
1246     }
1247   }
1248   /* match transaction ID against what we expected */
1249   if (ntohl(reply_msg->xid) != dhcp->xid) {
1250     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid));
1251     goto free_pbuf_and_return;
1252   }
1253   /* option fields could be unfold? */
1254   if (dhcp_unfold_reply(dhcp) != ERR_OK) {
1255     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("problem unfolding DHCP message - too short on memory?\n"));
1256     goto free_pbuf_and_return;
1257   }
1258
1259   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n"));
1260   /* obtain pointer to DHCP message type */
1261   options_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_MESSAGE_TYPE);
1262   if (options_ptr == NULL) {
1263     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
1264     goto free_pbuf_and_return;
1265   }
1266
1267   /* read DHCP message type */
1268   msg_type = dhcp_get_option_byte(options_ptr + 2);
1269   /* message type is DHCP ACK? */
1270   if (msg_type == DHCP_ACK) {
1271     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("DHCP_ACK received\n"));
1272     /* in requesting state? */
1273     if (dhcp->state == DHCP_REQUESTING) {
1274       dhcp_handle_ack(netif);
1275       dhcp->request_timeout = 0;
1276 #if DHCP_DOES_ARP_CHECK
1277       /* check if the acknowledged lease address is already in use */
1278       dhcp_check(netif);
1279 #else
1280       /* bind interface to the acknowledged lease address */
1281       dhcp_bind(netif);
1282 #endif
1283     }
1284     /* already bound to the given lease address? */
1285     else if ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING)) {
1286       dhcp->request_timeout = 0;
1287       dhcp_bind(netif);
1288     }
1289   }
1290   /* received a DHCP_NAK in appropriate state? */
1291   else if ((msg_type == DHCP_NAK) &&
1292     ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) ||
1293      (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING  ))) {
1294     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("DHCP_NAK received\n"));
1295     dhcp->request_timeout = 0;
1296     dhcp_handle_nak(netif);
1297   }
1298   /* received a DHCP_OFFER in DHCP_SELECTING state? */
1299   else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) {
1300     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("DHCP_OFFER received in DHCP_SELECTING state\n"));
1301     dhcp->request_timeout = 0;
1302     /* remember offered lease */
1303     dhcp_handle_offer(netif);
1304   }
1305 free_pbuf_and_return:
1306   pbuf_free(p);
1307   dhcp->p = NULL;
1308 }
1309
1310 /**
1311  * Create a DHCP request, fill in common headers
1312  *
1313  * @param netif the netif under DHCP control
1314  */
1315 static err_t
1316 dhcp_create_request(struct netif *netif)
1317 {
1318   struct dhcp *dhcp;
1319   u16_t i;
1320   LWIP_ERROR("dhcp_create_request: netif != NULL", (netif != NULL), return ERR_ARG;);
1321   dhcp = netif->dhcp;
1322   LWIP_ERROR("dhcp_create_request: dhcp != NULL", (dhcp != NULL), return ERR_VAL;);
1323   LWIP_ASSERT("dhcp_create_request: dhcp->p_out == NULL", dhcp->p_out == NULL);
1324   LWIP_ASSERT("dhcp_create_request: dhcp->msg_out == NULL", dhcp->msg_out == NULL);
1325   dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
1326   if (dhcp->p_out == NULL) {
1327     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("dhcp_create_request(): could not allocate pbuf\n"));
1328     return ERR_MEM;
1329   }
1330   LWIP_ASSERT("dhcp_create_request: check that first pbuf can hold struct dhcp_msg",
1331            (dhcp->p_out->len >= sizeof(struct dhcp_msg)));
1332
1333   /* give unique transaction identifier to this request */
1334   dhcp->xid = xid++;
1335   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("transaction id xid++(%"X32_F") dhcp->xid(%"U32_F")\n",xid,dhcp->xid));
1336
1337   dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload;
1338
1339   dhcp->msg_out->op = DHCP_BOOTREQUEST;
1340   /* TODO: make link layer independent */
1341   dhcp->msg_out->htype = DHCP_HTYPE_ETH;
1342   /* TODO: make link layer independent */
1343   dhcp->msg_out->hlen = DHCP_HLEN_ETH;
1344   dhcp->msg_out->hops = 0;
1345   dhcp->msg_out->xid = htonl(dhcp->xid);
1346   dhcp->msg_out->secs = 0;
1347   dhcp->msg_out->flags = 0;
1348   dhcp->msg_out->ciaddr.addr = netif->ip_addr.addr;
1349   dhcp->msg_out->yiaddr.addr = 0;
1350   dhcp->msg_out->siaddr.addr = 0;
1351   dhcp->msg_out->giaddr.addr = 0;
1352   for (i = 0; i < DHCP_CHADDR_LEN; i++) {
1353     /* copy netif hardware address, pad with zeroes */
1354     dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0/* pad byte*/;
1355   }
1356   for (i = 0; i < DHCP_SNAME_LEN; i++) {
1357     dhcp->msg_out->sname[i] = 0;
1358   }
1359   for (i = 0; i < DHCP_FILE_LEN; i++) {
1360     dhcp->msg_out->file[i] = 0;
1361   }
1362   dhcp->msg_out->cookie = htonl(0x63825363UL);
1363   dhcp->options_out_len = 0;
1364   /* fill options field with an incrementing array (for debugging purposes) */
1365   for (i = 0; i < DHCP_OPTIONS_LEN; i++) {
1366     dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */
1367   }
1368   return ERR_OK;
1369 }
1370
1371 /**
1372  * Free previously allocated memory used to send a DHCP request.
1373  *
1374  * @param netif the netif under DHCP control
1375  */
1376 static void
1377 dhcp_delete_request(struct netif *netif)
1378 {
1379   struct dhcp *dhcp;
1380   LWIP_ERROR("dhcp_delete_request: netif != NULL", (netif != NULL), return;);
1381   dhcp = netif->dhcp;
1382   LWIP_ERROR("dhcp_delete_request: dhcp != NULL", (dhcp != NULL), return;);
1383   LWIP_ASSERT("dhcp_delete_request: dhcp->p_out != NULL", dhcp->p_out != NULL);
1384   LWIP_ASSERT("dhcp_delete_request: dhcp->msg_out != NULL", dhcp->msg_out != NULL);
1385   if (dhcp->p_out != NULL) {
1386     pbuf_free(dhcp->p_out);
1387   }
1388   dhcp->p_out = NULL;
1389   dhcp->msg_out = NULL;
1390 }
1391
1392 /**
1393  * Add a DHCP message trailer
1394  *
1395  * Adds the END option to the DHCP message, and if
1396  * necessary, up to three padding bytes.
1397  *
1398  * @param dhcp DHCP state structure
1399  */
1400 static void
1401 dhcp_option_trailer(struct dhcp *dhcp)
1402 {
1403   LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;);
1404   LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL);
1405   LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
1406   dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
1407   /* packet is too small, or not 4 byte aligned? */
1408   while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) {
1409     /* LWIP_DEBUGF(DHCP_DEBUG,("dhcp_option_trailer:dhcp->options_out_len=%"U16_F", DHCP_OPTIONS_LEN=%"U16_F, dhcp->options_out_len, DHCP_OPTIONS_LEN)); */
1410     LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
1411     /* add a fill/padding byte */
1412     dhcp->msg_out->options[dhcp->options_out_len++] = 0;
1413   }
1414 }
1415
1416 /**
1417  * Find the offset of a DHCP option inside the DHCP message.
1418  *
1419  * @param dhcp DHCP client
1420  * @param option_type
1421  *
1422  * @return a byte offset into the UDP message where the option was found, or
1423  * zero if the given option was not found.
1424  */
1425 static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
1426 {
1427   u8_t overload = DHCP_OVERLOAD_NONE;
1428
1429   /* options available? */
1430   if ((dhcp->options_in != NULL) && (dhcp->options_in_len > 0)) {
1431     /* start with options field */
1432     u8_t *options = (u8_t *)dhcp->options_in;
1433     u16_t offset = 0;
1434     /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
1435     while ((offset < dhcp->options_in_len) && (options[offset] != DHCP_OPTION_END)) {
1436       /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
1437       /* are the sname and/or file field overloaded with options? */
1438       if (options[offset] == DHCP_OPTION_OVERLOAD) {
1439         LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2, ("overloaded message detected\n"));
1440         /* skip option type and length */
1441         offset += 2;
1442         overload = options[offset++];
1443       }
1444       /* requested option found */
1445       else if (options[offset] == option_type) {
1446         LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("option found at offset %"U16_F" in options\n", offset));
1447         return &options[offset];
1448       /* skip option */
1449       } else {
1450          LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", options[offset]));
1451         /* skip option type */
1452         offset++;
1453         /* skip option length, and then length bytes */
1454         offset += 1 + options[offset];
1455       }
1456     }
1457     /* is this an overloaded message? */
1458     if (overload != DHCP_OVERLOAD_NONE) {
1459       u16_t field_len;
1460       if (overload == DHCP_OVERLOAD_FILE) {
1461         LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("overloaded file field\n"));
1462         options = (u8_t *)&dhcp->msg_in->file;
1463         field_len = DHCP_FILE_LEN;
1464       } else if (overload == DHCP_OVERLOAD_SNAME) {
1465         LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("overloaded sname field\n"));
1466         options = (u8_t *)&dhcp->msg_in->sname;
1467         field_len = DHCP_SNAME_LEN;
1468       /* TODO: check if else if () is necessary */
1469       } else {
1470         LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("overloaded sname and file field\n"));
1471         options = (u8_t *)&dhcp->msg_in->sname;
1472         field_len = DHCP_FILE_LEN + DHCP_SNAME_LEN;
1473       }
1474       offset = 0;
1475
1476       /* at least 1 byte to read and no end marker */
1477       while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) {
1478         if (options[offset] == option_type) {
1479            LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("option found at offset=%"U16_F"\n", offset));
1480           return &options[offset];
1481         /* skip option */
1482         } else {
1483           LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("skipping option %"U16_F"\n", options[offset]));
1484           /* skip option type */
1485           offset++;
1486           offset += 1 + options[offset];
1487         }
1488       }
1489     }
1490   }
1491   return NULL;
1492 }
1493
1494 /**
1495  * Return the byte of DHCP option data.
1496  *
1497  * @param client DHCP client.
1498  * @param ptr pointer obtained by dhcp_get_option_ptr().
1499  *
1500  * @return byte value at the given address.
1501  */
1502 static u8_t
1503 dhcp_get_option_byte(u8_t *ptr)
1504 {
1505   LWIP_DEBUGF(DHCP_DEBUG, ("option byte value=%"U16_F"\n", (u16_t)(*ptr)));
1506   return *ptr;
1507 }
1508
1509 #if 0 /* currently unused */
1510 /**
1511  * Return the 16-bit value of DHCP option data.
1512  *
1513  * @param client DHCP client.
1514  * @param ptr pointer obtained by dhcp_get_option_ptr().
1515  *
1516  * @return byte value at the given address.
1517  */
1518 static u16_t
1519 dhcp_get_option_short(u8_t *ptr)
1520 {
1521   u16_t value;
1522   value = *ptr++ << 8;
1523   value |= *ptr;
1524   LWIP_DEBUGF(DHCP_DEBUG, ("option short value=%"U16_F"\n", value));
1525   return value;
1526 }
1527 #endif
1528
1529 /**
1530  * Return the 32-bit value of DHCP option data.
1531  *
1532  * @param client DHCP client.
1533  * @param ptr pointer obtained by dhcp_get_option_ptr().
1534  *
1535  * @return byte value at the given address.
1536  */
1537 static u32_t dhcp_get_option_long(u8_t *ptr)
1538 {
1539   u32_t value;
1540   value = (u32_t)(*ptr++) << 24;
1541   value |= (u32_t)(*ptr++) << 16;
1542   value |= (u32_t)(*ptr++) << 8;
1543   value |= (u32_t)(*ptr++);
1544   LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%"U32_F"\n", value));
1545   return value;
1546 }
1547
1548 #endif /* LWIP_DHCP */