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/** Default for DHCP_GLOBAL_XID is 0xABCD0000
90 * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g.
91 *  #define DHCP_GLOBAL_XID_HEADER "stdlib.h"
92 *  #define DHCP_GLOBAL_XID rand()
93 */
94#ifdef DHCP_GLOBAL_XID_HEADER
95#include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */
96#endif
97
98/** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU
99 * MTU is checked to be big enough in dhcp_start */
100#define DHCP_MAX_MSG_LEN(netif)        (netif->mtu)
101#define DHCP_MAX_MSG_LEN_MIN_REQUIRED  576
102
103/* DHCP client state machine functions */
104static void dhcp_handle_ack(struct netif *netif);
105static void dhcp_handle_nak(struct netif *netif);
106static void dhcp_handle_offer(struct netif *netif);
107
108static err_t dhcp_discover(struct netif *netif);
109static err_t dhcp_select(struct netif *netif);
110static void dhcp_check(struct netif *netif);
111static void dhcp_bind(struct netif *netif);
112
113#if DHCP_DOES_ARP_CHECK
114static err_t dhcp_decline(struct netif *netif);
115#endif                          /* DHCP_DOES_ARP_CHECK */
116static err_t dhcp_rebind(struct netif *netif);
117static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
118
119/* receive, unfold, parse and free incoming messages */
120static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p,
121                      struct ip_addr *addr, u16_t port);
122static err_t dhcp_unfold_reply(struct dhcp *dhcp);
123static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type);
124static u8_t dhcp_get_option_byte(u8_t * ptr);
125
126#if 0
127static u16_t dhcp_get_option_short(u8_t * ptr);
128#endif
129static u32_t dhcp_get_option_long(u8_t * ptr);
130static void dhcp_free_reply(struct dhcp *dhcp);
131
132/* set the DHCP timers */
133static void dhcp_timeout(struct netif *netif);
134static void dhcp_t1_timeout(struct netif *netif);
135static void dhcp_t2_timeout(struct netif *netif);
136
137/* build outgoing messages */
138/* create a DHCP request, fill in common headers */
139static err_t dhcp_create_request(struct netif *netif);
140
141/* free a DHCP request */
142static void dhcp_delete_request(struct netif *netif);
143
144/* add a DHCP option (type, then length in bytes) */
145static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len);
146
147/* add option values */
148static void dhcp_option_byte(struct dhcp *dhcp, u8_t value);
149static void dhcp_option_short(struct dhcp *dhcp, u16_t value);
150static void dhcp_option_long(struct dhcp *dhcp, u32_t value);
151
152/* always add the DHCP options trailer to end and pad */
153static void dhcp_option_trailer(struct dhcp *dhcp);
154
155/**
156 * Back-off the DHCP client (because of a received NAK response).
157 *
158 * Back-off the DHCP client because of a received NAK. Receiving a
159 * NAK means the client asked for something non-sensible, for
160 * example when it tries to renew a lease obtained on another network.
161 *
162 * We clear any existing set IP address and restart DHCP negotiation
163 * afresh (as per RFC2131 3.2.3).
164 *
165 * @param netif the netif under DHCP control
166 */
167static void dhcp_handle_nak(struct netif *netif)
168{
169    struct dhcp *dhcp = netif->dhcp;
170
171    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3,
172                ("dhcp_handle_nak(netif=%p) %c%c%" U16_F "\n", (void *) netif,
173                 netif->name[0], netif->name[1], (u16_t) netif->num));
174    /* Set the interface down since the address must no longer be used, as per RFC2131 */
175    netif_set_down(netif);
176    /* remove IP address from interface */
177    netif_set_ipaddr(netif, IP_ADDR_ANY);
178    netif_set_gw(netif, IP_ADDR_ANY);
179    netif_set_netmask(netif, IP_ADDR_ANY);
180    /* Change to a defined state */
181    dhcp_set_state(dhcp, DHCP_BACKING_OFF);
182    /* We can immediately restart discovery */
183    dhcp_discover(netif);
184}
185
186/**
187 * Checks if the offered IP address is already in use.
188 *
189 * It does so by sending an ARP request for the offered address and
190 * entering CHECKING state. If no ARP reply is received within a small
191 * interval, the address is assumed to be free for use by us.
192 *
193 * @param netif the netif under DHCP control
194 */
195static void dhcp_check(struct netif *netif)
196{
197    struct dhcp *dhcp = netif->dhcp;
198    err_t result;
199    u16_t msecs;
200
201    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3,
202                ("dhcp_check(netif=%p) %c%c\n", (void *) netif,
203                 (s16_t) netif->name[0], (s16_t) netif->name[1]));
204    dhcp_set_state(dhcp, DHCP_CHECKING);
205    /* create an ARP query for the offered IP address, expecting that no host
206       responds, as the IP address should not be in use. */
207    result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
208    if (result != ERR_OK) {
209        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
210                    ("dhcp_check: could not perform ARP query\n"));
211    }
212    dhcp->tries++;
213    msecs = 500;
214    dhcp->request_timeout =
215      (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
216    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
217                ("dhcp_check(): set request timeout %" U16_F " msecs\n",
218                 msecs));
219}
220
221/**
222 * Remember the configuration offered by a DHCP server.
223 *
224 * @param netif the netif under DHCP control
225 */
226static void dhcp_handle_offer(struct netif *netif)
227{
228    struct dhcp *dhcp = netif->dhcp;
229
230    /* obtain the server address */
231    u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID);
232
233    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3,
234                ("dhcp_handle_offer(netif=%p) %c%c%" U16_F "\n", (void *) netif,
235                 netif->name[0], netif->name[1], (u16_t) netif->num));
236    if (option_ptr != NULL) {
237        dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
238        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE,
239                    ("dhcp_handle_offer(): server 0x%08" X32_F "\n",
240                     dhcp->server_ip_addr.addr));
241        /* remember offered address */
242        ip_addr_set(&dhcp->offered_ip_addr,
243                    (struct ip_addr *) &dhcp->msg_in->yiaddr);
244        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE,
245                    ("dhcp_handle_offer(): offer for 0x%08" X32_F "\n",
246                     dhcp->offered_ip_addr.addr));
247
248        dhcp_select(netif);
249    }
250}
251
252/**
253 * Select a DHCP server offer out of all offers.
254 *
255 * Simply select the first offer received.
256 *
257 * @param netif the netif under DHCP control
258 * @return lwIP specific error (see error.h)
259 */
260static err_t dhcp_select(struct netif *netif)
261{
262    struct dhcp *dhcp = netif->dhcp;
263    err_t result;
264    u16_t msecs;
265
266#if LWIP_NETIF_HOSTNAME
267    const char *p;
268#endif                          /* LWIP_NETIF_HOSTNAME */
269
270    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3,
271                ("dhcp_select(netif=%p) %c%c%" U16_F "\n", (void *) netif,
272                 netif->name[0], netif->name[1], (u16_t) netif->num));
273    dhcp_set_state(dhcp, DHCP_REQUESTING);
274
275    /* create and initialize the DHCP message header */
276    result = dhcp_create_request(netif);
277    if (result == ERR_OK) {
278        dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE,
279                    DHCP_OPTION_MESSAGE_TYPE_LEN);
280        dhcp_option_byte(dhcp, DHCP_REQUEST);
281
282        dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE,
283                    DHCP_OPTION_MAX_MSG_SIZE_LEN);
284        dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
285
286        /* MUST request the offered IP address */
287        dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
288        dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
289
290        dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
291        dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
292
293        dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST,
294                    4 /*num options */ );
295        dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
296        dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
297        dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
298        dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
299
300#if LWIP_NETIF_HOSTNAME
301        p = (const char *) netif->hostname;
302        if (p != NULL) {
303            dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, strlen(p));
304            while (*p) {
305                dhcp_option_byte(dhcp, *p++);
306            }
307        }
308#endif                          /* LWIP_NETIF_HOSTNAME */
309
310        dhcp_option_trailer(dhcp);
311        /* shrink the pbuf to the actual content length */
312        pbuf_realloc(dhcp->p_out,
313                     sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN +
314                     dhcp->options_out_len);
315
316        /* TODO: we really should bind to a specific local interface here
317           but we cannot specify an unconfigured netif as it is addressless */
318        /* send broadcast to any DHCP server */
319        udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST,
320                      DHCP_SERVER_PORT, netif);
321        /* reconnect to any (or to server here?!) */
322        udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
323        dhcp_delete_request(netif);
324        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
325                    ("dhcp_select: REQUESTING\n"));
326    } else {
327        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
328                    ("dhcp_select: could not allocate DHCP request\n"));
329    }
330    dhcp->tries++;
331    msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
332    dhcp->request_timeout =
333      (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
334    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE,
335                ("dhcp_select(): set request timeout %" U16_F " msecs\n",
336                 msecs));
337    return result;
338}
339
340/**
341 * The DHCP timer that checks for lease renewal/rebind timeouts.
342 *
343 */
344void dhcp_coarse_tmr(void)
345{
346    struct netif *netif = netif_list;
347
348    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n"));
349    /* iterate through all network interfaces */
350    while (netif != NULL) {
351        /* only act on DHCP configured interfaces */
352        if (netif->dhcp != NULL) {
353            /* timer is active (non zero), and triggers (zeroes) now? */
354            if (netif->dhcp->t2_timeout-- == 1) {
355                LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
356                            ("dhcp_coarse_tmr(): t2 timeout\n"));
357                /* this clients' rebind timeout triggered */
358                dhcp_t2_timeout(netif);
359                /* timer is active (non zero), and triggers (zeroes) now */
360            } else if (netif->dhcp->t1_timeout-- == 1) {
361                LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
362                            ("dhcp_coarse_tmr(): t1 timeout\n"));
363                /* this clients' renewal timeout triggered */
364                dhcp_t1_timeout(netif);
365            }
366        }
367        /* proceed to next netif */
368        netif = netif->next;
369    }
370}
371
372/**
373 * DHCP transaction timeout handling
374 *
375 * A DHCP server is expected to respond within a short period of time.
376 * This timer checks whether an outstanding DHCP request is timed out.
377 *
378 */
379void dhcp_fine_tmr(void)
380{
381    struct netif *netif = netif_list;
382
383    /* loop through netif's */
384    while (netif != NULL) {
385        /* only act on DHCP configured interfaces */
386        if (netif->dhcp != NULL) {
387            /* timer is active (non zero), and is about to trigger now */
388            if (netif->dhcp->request_timeout > 1) {
389                netif->dhcp->request_timeout--;
390            } else if (netif->dhcp->request_timeout == 1) {
391                netif->dhcp->request_timeout--;
392                /* { netif->dhcp->request_timeout == 0 } */
393                LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
394                            ("dhcp_fine_tmr(): request timeout\n"));
395                /* this clients' request timeout triggered */
396                dhcp_timeout(netif);
397            }
398        }
399        /* proceed to next network interface */
400        netif = netif->next;
401    }
402}
403
404/**
405 * A DHCP negotiation transaction, or ARP request, has timed out.
406 *
407 * The timer that was started with the DHCP or ARP request has
408 * timed out, indicating no response was received in time.
409 *
410 * @param netif the netif under DHCP control
411 */
412static void dhcp_timeout(struct netif *netif)
413{
414    struct dhcp *dhcp = netif->dhcp;
415
416    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_timeout()\n"));
417    /* back-off period has passed, or server selection timed out */
418    if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) {
419        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
420                    ("dhcp_timeout(): restarting discovery\n"));
421        dhcp_discover(netif);
422        /* receiving the requested lease timed out */
423    } else if (dhcp->state == DHCP_REQUESTING) {
424        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
425                    ("dhcp_timeout(): REQUESTING, DHCP request timed out\n"));
426        if (dhcp->tries <= 5) {
427            dhcp_select(netif);
428        } else {
429            LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
430                        ("dhcp_timeout(): REQUESTING, releasing, restarting\n"));
431            dhcp_release(netif);
432            dhcp_discover(netif);
433        }
434        /* received no ARP reply for the offered address (which is good) */
435    } else if (dhcp->state == DHCP_CHECKING) {
436        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
437                    ("dhcp_timeout(): CHECKING, ARP request timed out\n"));
438        if (dhcp->tries <= 1) {
439            dhcp_check(netif);
440            /* no ARP replies on the offered address,
441               looks like the IP address is indeed free */
442        } else {
443            /* bind the interface to the offered address */
444            dhcp_bind(netif);
445        }
446    }
447    /* did not get response to renew request? */
448    else if (dhcp->state == DHCP_RENEWING) {
449        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
450                    ("dhcp_timeout(): RENEWING, DHCP request timed out\n"));
451        /* just retry renewal */
452        /* note that the rebind timer will eventually time-out if renew does not work */
453        dhcp_renew(netif);
454        /* did not get response to rebind request? */
455    } else if (dhcp->state == DHCP_REBINDING) {
456        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
457                    ("dhcp_timeout(): REBINDING, DHCP request timed out\n"));
458        if (dhcp->tries <= 8) {
459            dhcp_rebind(netif);
460        } else {
461            LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
462                        ("dhcp_timeout(): RELEASING, DISCOVERING\n"));
463            dhcp_release(netif);
464            dhcp_discover(netif);
465        }
466    }
467}
468
469/**
470 * The renewal period has timed out.
471 *
472 * @param netif the netif under DHCP control
473 */
474static void dhcp_t1_timeout(struct netif *netif)
475{
476    struct dhcp *dhcp = netif->dhcp;
477
478    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n"));
479    if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND)
480        || (dhcp->state == DHCP_RENEWING)) {
481        /* just retry to renew - note that the rebind timer (t2) will
482         * eventually time-out if renew tries fail. */
483        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
484                    ("dhcp_t1_timeout(): must renew\n"));
485        dhcp_renew(netif);
486    }
487}
488
489/**
490 * The rebind period has timed out.
491 *
492 * @param netif the netif under DHCP control
493 */
494static void dhcp_t2_timeout(struct netif *netif)
495{
496    struct dhcp *dhcp = netif->dhcp;
497
498    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
499                ("dhcp_t2_timeout()\n"));
500    if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND)
501        || (dhcp->state == DHCP_RENEWING)) {
502        /* just retry to rebind */
503        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
504                    ("dhcp_t2_timeout(): must rebind\n"));
505        dhcp_rebind(netif);
506    }
507}
508
509/**
510 * Handle a DHCP ACK packet
511 *
512 * @param netif the netif under DHCP control
513 */
514static void dhcp_handle_ack(struct netif *netif)
515{
516    struct dhcp *dhcp = netif->dhcp;
517    u8_t *option_ptr;
518
519    /* clear options we might not get from the ACK */
520    dhcp->offered_sn_mask.addr = 0;
521    dhcp->offered_gw_addr.addr = 0;
522    dhcp->offered_bc_addr.addr = 0;
523
524    /* lease time given? */
525    option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_LEASE_TIME);
526    if (option_ptr != NULL) {
527        /* remember offered lease time */
528        dhcp->offered_t0_lease = dhcp_get_option_long(option_ptr + 2);
529    }
530    /* renewal period given? */
531    option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T1);
532    if (option_ptr != NULL) {
533        /* remember given renewal period */
534        dhcp->offered_t1_renew = dhcp_get_option_long(option_ptr + 2);
535    } else {
536        /* calculate safe periods for renewal */
537        dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2;
538    }
539
540    /* renewal period given? */
541    option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T2);
542    if (option_ptr != NULL) {
543        /* remember given rebind period */
544        dhcp->offered_t2_rebind = dhcp_get_option_long(option_ptr + 2);
545    } else {
546        /* calculate safe periods for rebinding */
547        dhcp->offered_t2_rebind = dhcp->offered_t0_lease;
548    }
549
550    /* (y)our internet address */
551    ip_addr_set(&dhcp->offered_ip_addr, &dhcp->msg_in->yiaddr);
552
553/**
554 * Patch #1308
555 * TODO: we must check if the file field is not overloaded by DHCP options!
556 */
557#if 0
558    /* boot server address */
559    ip_addr_set(&dhcp->offered_si_addr, &dhcp->msg_in->siaddr);
560    /* boot file name */
561    if (dhcp->msg_in->file[0]) {
562        dhcp->boot_file_name = mem_malloc(strlen(dhcp->msg_in->file) + 1);
563        strcpy(dhcp->boot_file_name, dhcp->msg_in->file);
564    }
565#endif
566
567    /* subnet mask */
568    option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SUBNET_MASK);
569    /* subnet mask given? */
570    if (option_ptr != NULL) {
571        dhcp->offered_sn_mask.addr =
572          htonl(dhcp_get_option_long(&option_ptr[2]));
573    }
574
575    /* gateway router */
576    option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_ROUTER);
577    if (option_ptr != NULL) {
578        dhcp->offered_gw_addr.addr =
579          htonl(dhcp_get_option_long(&option_ptr[2]));
580    }
581
582    /* broadcast address */
583    option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_BROADCAST);
584    if (option_ptr != NULL) {
585        dhcp->offered_bc_addr.addr =
586          htonl(dhcp_get_option_long(&option_ptr[2]));
587    }
588
589    /* DNS servers */
590    option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_DNS_SERVER);
591    if (option_ptr != NULL) {
592        u8_t n;
593
594        dhcp->dns_count =
595          dhcp_get_option_byte(&option_ptr[1]) / (u32_t) sizeof(struct ip_addr);
596        /* limit to at most DHCP_MAX_DNS DNS servers */
597        if (dhcp->dns_count > DHCP_MAX_DNS)
598            dhcp->dns_count = DHCP_MAX_DNS;
599        for (n = 0; n < dhcp->dns_count; n++) {
600            dhcp->offered_dns_addr[n].addr =
601              htonl(dhcp_get_option_long(&option_ptr[2 + n * 4]));
602#if LWIP_DNS
603            dns_setserver(n,
604                          (struct ip_addr
605                           *) (&(dhcp->offered_dns_addr[n].addr)));
606#endif                          /* LWIP_DNS */
607        }
608#if LWIP_DNS
609        dns_setserver(n, (struct ip_addr *) (&ip_addr_any));
610#endif                          /* LWIP_DNS */
611    }
612}
613
614/**
615 * Start DHCP negotiation for a network interface.
616 *
617 * If no DHCP client instance was attached to this interface,
618 * a new client is created first. If a DHCP client instance
619 * was already present, it restarts negotiation.
620 *
621 * @param netif The lwIP network interface
622 * @return lwIP error code
623 * - ERR_OK - No error
624 * - ERR_MEM - Out of memory
625 */
626err_t dhcp_start(struct netif *netif)
627{
628    struct dhcp *dhcp;
629    err_t result = ERR_OK;
630    /* FIXME: make sure that if the calling process is not owner of LWIP stack
631     * then it should not be allowed to continue. */
632    LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
633    dhcp = netif->dhcp;
634    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
635                ("dhcp_start(netif=%p) %c%c%" U16_F "\n", (void *) netif,
636                 netif->name[0], netif->name[1], (u16_t) netif->num));
637    /* Remove the flag that says this netif is handled by DHCP,
638       it is set when we succeeded starting. */
639    netif->flags &= ~NETIF_FLAG_DHCP;
640
641    /* check MTU of the netif */
642    if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) {
643        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
644                    ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n"));
645    printf("here 3 mtu %u < %u\n", netif->mtu, DHCP_MAX_MSG_LEN_MIN_REQUIRED);
646        return ERR_MEM;
647    }
648
649    /* no DHCP client attached yet? */
650    if (dhcp == NULL) {
651        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
652                    ("dhcp_start(): starting new DHCP client\n"));
653        dhcp = mem_malloc(sizeof(struct dhcp));
654        if (dhcp == NULL) {
655            LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
656                        ("dhcp_start(): could not allocate dhcp\n"));
657            return ERR_MEM;
658        }
659        /* store this dhcp client in the netif */
660        netif->dhcp = dhcp;
661        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
662                    ("dhcp_start(): allocated dhcp"));
663        /* already has DHCP client attached */
664    } else {
665        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3,
666                    ("dhcp_start(): restarting DHCP configuration\n"));
667        if (dhcp->pcb != NULL) {
668            udp_remove(dhcp->pcb);
669        }
670        if (dhcp->p != NULL) {
671            pbuf_free(dhcp->p);
672        }
673    }
674    /* clear data structure */
675    memset(dhcp, 0, sizeof(struct dhcp));
676    /* allocate UDP PCB */
677    dhcp->pcb = udp_new();
678    if (dhcp->pcb == NULL) {
679        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
680                    ("dhcp_start(): could not obtain pcb\n"));
681        mem_free((void *) dhcp);
682        netif->dhcp = dhcp = NULL;
683        return ERR_MEM;
684    }
685#if IP_SOF_BROADCAST
686    dhcp->pcb->so_options |= SOF_BROADCAST;
687#endif                          /* IP_SOF_BROADCAST */
688    /* set up local and remote port for the pcb */
689    udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
690    udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
691    /* set up the recv callback and argument */
692    udp_recv(dhcp->pcb, dhcp_recv, netif);
693    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
694                ("dhcp_start(): starting DHCP configuration\n"));
695    /* (re)start the DHCP negotiation */
696    result = dhcp_discover(netif);
697    if (result != ERR_OK) {
698        /* free resources allocated above */
699        dhcp_stop(netif);
700        return ERR_MEM;
701    }
702    /* Set the flag that says this netif is handled by DHCP. */
703    netif->flags |= NETIF_FLAG_DHCP;
704    return result;
705}
706
707/**
708 * Inform a DHCP server of our manual configuration.
709 *
710 * This informs DHCP servers of our fixed IP address configuration
711 * by sending an INFORM message. It does not involve DHCP address
712 * configuration, it is just here to be nice to the network.
713 *
714 * @param netif The lwIP network interface
715 */
716void dhcp_inform(struct netif *netif)
717{
718    struct dhcp *dhcp, *old_dhcp = netif->dhcp;
719    err_t result = ERR_OK;
720
721    dhcp = mem_malloc(sizeof(struct dhcp));
722    if (dhcp == NULL) {
723        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
724                    ("dhcp_inform(): could not allocate dhcp\n"));
725        return;
726    }
727    netif->dhcp = dhcp;
728    memset(dhcp, 0, sizeof(struct dhcp));
729
730    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
731                ("dhcp_inform(): allocated dhcp\n"));
732    dhcp->pcb = udp_new();
733    if (dhcp->pcb == NULL) {
734        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
735                    ("dhcp_inform(): could not obtain pcb"));
736        mem_free((void *) dhcp);
737        return;
738    }
739    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
740                ("dhcp_inform(): created new udp pcb\n"));
741    /* create and initialize the DHCP message header */
742    result = dhcp_create_request(netif);
743    if (result == ERR_OK) {
744
745        dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE,
746                    DHCP_OPTION_MESSAGE_TYPE_LEN);
747        dhcp_option_byte(dhcp, DHCP_INFORM);
748
749        dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE,
750                    DHCP_OPTION_MAX_MSG_SIZE_LEN);
751        dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
752
753        dhcp_option_trailer(dhcp);
754
755        pbuf_realloc(dhcp->p_out,
756                     sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN +
757                     dhcp->options_out_len);
758
759#if IP_SOF_BROADCAST
760        dhcp->pcb->so_options |= SOF_BROADCAST;
761#endif                          /* IP_SOF_BROADCAST */
762        udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
763        udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
764        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
765                    ("dhcp_inform: INFORMING\n"));
766        udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST,
767                      DHCP_SERVER_PORT, netif);
768        udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
769        dhcp_delete_request(netif);
770    } else {
771        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
772                    ("dhcp_inform: could not allocate DHCP request\n"));
773    }
774
775    if (dhcp->pcb != NULL) {
776        udp_remove(dhcp->pcb);
777    }
778    dhcp->pcb = NULL;
779    mem_free((void *) dhcp);
780    netif->dhcp = old_dhcp;
781}
782
783#if DHCP_DOES_ARP_CHECK
784/**
785 * Match an ARP reply with the offered IP address.
786 *
787 * @param netif the network interface on which the reply was received
788 * @param addr The IP address we received a reply from
789 */
790void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
791{
792    LWIP_ERROR("netif != NULL", (netif != NULL), return;
793      );
794    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_arp_reply()\n"));
795    /* is a DHCP client doing an ARP check? */
796    if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
797        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
798                    ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08" X32_F
799                     "\n", addr->addr));
800        /* did a host respond with the address we
801           were offered by the DHCP server? */
802        if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
803            /* we will not accept the offered address */
804            LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 1,
805                        ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
806            dhcp_decline(netif);
807        }
808    }
809}
810
811/**
812 * Decline an offered lease.
813 *
814 * Tell the DHCP server we do not accept the offered address.
815 * One reason to decline the lease is when we find out the address
816 * is already in use by another host (through ARP).
817 *
818 * @param netif the netif under DHCP control
819 */
820static err_t dhcp_decline(struct netif *netif)
821{
822    struct dhcp *dhcp = netif->dhcp;
823    err_t result = ERR_OK;
824    u16_t msecs;
825
826    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_decline()\n"));
827    dhcp_set_state(dhcp, DHCP_BACKING_OFF);
828    /* create and initialize the DHCP message header */
829    result = dhcp_create_request(netif);
830    if (result == ERR_OK) {
831        dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE,
832                    DHCP_OPTION_MESSAGE_TYPE_LEN);
833        dhcp_option_byte(dhcp, DHCP_DECLINE);
834
835        dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
836        dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
837
838        dhcp_option_trailer(dhcp);
839        /* resize pbuf to reflect true size of options */
840        pbuf_realloc(dhcp->p_out,
841                     sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN +
842                     dhcp->options_out_len);
843
844        /* @todo: should we really connect here? we are performing sendto() */
845        udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
846        /* per section 4.4.4, broadcast DECLINE messages */
847        udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST,
848                      DHCP_SERVER_PORT, netif);
849        dhcp_delete_request(netif);
850        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
851                    ("dhcp_decline: BACKING OFF\n"));
852    } else {
853        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
854                    ("dhcp_decline: could not allocate DHCP request\n"));
855    }
856    dhcp->tries++;
857    msecs = 10 * 1000;
858    dhcp->request_timeout =
859      (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
860    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
861                ("dhcp_decline(): set request timeout %" U16_F " msecs\n",
862                 msecs));
863    return result;
864}
865#endif
866
867
868/**
869 * Start the DHCP process, discover a DHCP server.
870 *
871 * @param netif the netif under DHCP control
872 */
873static err_t dhcp_discover(struct netif *netif)
874{
875    struct dhcp *dhcp = netif->dhcp;
876    err_t result = ERR_OK;
877    u16_t msecs;
878
879    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_discover()\n"));
880    ip_addr_set(&dhcp->offered_ip_addr, IP_ADDR_ANY);
881    dhcp_set_state(dhcp, DHCP_SELECTING);
882    /* create and initialize the DHCP message header */
883    result = dhcp_create_request(netif);
884    if (result == ERR_OK) {
885        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
886                    ("dhcp_discover: making request\n"));
887        dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE,
888                    DHCP_OPTION_MESSAGE_TYPE_LEN);
889        dhcp_option_byte(dhcp, DHCP_DISCOVER);
890
891        dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE,
892                    DHCP_OPTION_MAX_MSG_SIZE_LEN);
893        dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
894
895        dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST,
896                    4 /*num options */ );
897        dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
898        dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
899        dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
900        dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
901
902        dhcp_option_trailer(dhcp);
903
904        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
905                    ("dhcp_discover: realloc()ing\n"));
906        pbuf_realloc(dhcp->p_out,
907                     sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN +
908                     dhcp->options_out_len);
909
910        udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
911        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
912                    ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
913        udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST,
914                      DHCP_SERVER_PORT, netif);
915        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
916                    ("dhcp_discover: deleting()ing\n"));
917        dhcp_delete_request(netif);
918        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
919                    ("dhcp_discover: SELECTING\n"));
920    } else {
921        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
922                    ("dhcp_discover: could not allocate DHCP request\n"));
923    }
924    dhcp->tries++;
925#if LWIP_DHCP_AUTOIP_COOP
926    if (dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES
927        && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) {
928        dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON;
929        autoip_start(netif);
930    }
931#endif                          /* LWIP_DHCP_AUTOIP_COOP */
932    msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
933    dhcp->request_timeout =
934      (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
935    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
936                ("dhcp_discover(): set request timeout %" U16_F " msecs\n",
937                 msecs));
938    return result;
939}
940
941
942/**
943 * Bind the interface to the offered IP address.
944 *
945 * @param netif network interface to bind to the offered address
946 */
947static void dhcp_bind(struct netif *netif)
948{
949    u32_t timeout;
950    struct dhcp *dhcp;
951    struct ip_addr sn_mask, gw_addr;
952
953    LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;
954      );
955    dhcp = netif->dhcp;
956    LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;
957      );
958    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3,
959                ("dhcp_bind(netif=%p) %c%c%" U16_F "\n", (void *) netif,
960                 netif->name[0], netif->name[1], (u16_t) netif->num));
961
962    /* temporary DHCP lease? */
963    if (dhcp->offered_t1_renew != 0xffffffffUL) {
964        /* set renewal period timer */
965        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
966                    ("dhcp_bind(): t1 renewal timer %" U32_F " secs\n",
967                     dhcp->offered_t1_renew));
968        timeout =
969          (dhcp->offered_t1_renew +
970           DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
971        if (timeout > 0xffff) {
972            timeout = 0xffff;
973        }
974        dhcp->t1_timeout = (u16_t) timeout;
975        if (dhcp->t1_timeout == 0) {
976            dhcp->t1_timeout = 1;
977        }
978        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
979                    ("dhcp_bind(): set request timeout %" U32_F " msecs\n",
980                     dhcp->offered_t1_renew * 1000));
981    }
982    /* set renewal period timer */
983    if (dhcp->offered_t2_rebind != 0xffffffffUL) {
984        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
985                    ("dhcp_bind(): t2 rebind timer %" U32_F " secs\n",
986                     dhcp->offered_t2_rebind));
987        timeout =
988          (dhcp->offered_t2_rebind +
989           DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
990        if (timeout > 0xffff) {
991            timeout = 0xffff;
992        }
993        dhcp->t2_timeout = (u16_t) timeout;
994        if (dhcp->t2_timeout == 0) {
995            dhcp->t2_timeout = 1;
996        }
997        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
998                    ("dhcp_bind(): set request timeout %" U32_F " msecs\n",
999                     dhcp->offered_t2_rebind * 1000));
1000    }
1001    /* copy offered network mask */
1002    ip_addr_set(&sn_mask, &dhcp->offered_sn_mask);
1003
1004    /* subnet mask not given? */
1005    /* TODO: this is not a valid check. what if the network mask is 0? */
1006    if (sn_mask.addr == 0) {
1007        /* choose a safe subnet mask given the network class */
1008        u8_t first_octet = ip4_addr1(&sn_mask);
1009
1010        if (first_octet <= 127) {
1011            sn_mask.addr = htonl(0xff000000);
1012        } else if (first_octet >= 192) {
1013            sn_mask.addr = htonl(0xffffff00);
1014        } else {
1015            sn_mask.addr = htonl(0xffff0000);
1016        }
1017    }
1018
1019    ip_addr_set(&gw_addr, &dhcp->offered_gw_addr);
1020    /* gateway address not given? */
1021    if (gw_addr.addr == 0) {
1022        /* copy network address */
1023        gw_addr.addr = (dhcp->offered_ip_addr.addr & sn_mask.addr);
1024        /* use first host address on network as gateway */
1025        gw_addr.addr |= htonl(0x00000001);
1026    }
1027#if LWIP_DHCP_AUTOIP_COOP
1028    if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
1029        autoip_stop(netif);
1030        dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
1031    }
1032#endif                          /* LWIP_DHCP_AUTOIP_COOP */
1033
1034    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE,
1035                ("dhcp_bind(): IP: 0x%08" X32_F "\n",
1036                 dhcp->offered_ip_addr.addr));
1037    netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
1038    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE,
1039                ("dhcp_bind(): SN: 0x%08" X32_F "\n", sn_mask.addr));
1040    netif_set_netmask(netif, &sn_mask);
1041    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE,
1042                ("dhcp_bind(): GW: 0x%08" X32_F "\n", gw_addr.addr));
1043    netif_set_gw(netif, &gw_addr);
1044    /* bring the interface up */
1045    netif_set_up(netif);
1046    /* netif is now bound to DHCP leased address */
1047    dhcp_set_state(dhcp, DHCP_BOUND);
1048}
1049
1050/**
1051 * Renew an existing DHCP lease at the involved DHCP server.
1052 *
1053 * @param netif network interface which must renew its lease
1054 */
1055err_t dhcp_renew(struct netif *netif)
1056{
1057    struct dhcp *dhcp = netif->dhcp;
1058    err_t result;
1059    u16_t msecs;
1060
1061#if LWIP_NETIF_HOSTNAME
1062    const char *p;
1063#endif                          /* LWIP_NETIF_HOSTNAME */
1064    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_renew()\n"));
1065    dhcp_set_state(dhcp, DHCP_RENEWING);
1066
1067    /* create and initialize the DHCP message header */
1068    result = dhcp_create_request(netif);
1069    if (result == ERR_OK) {
1070
1071        dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE,
1072                    DHCP_OPTION_MESSAGE_TYPE_LEN);
1073        dhcp_option_byte(dhcp, DHCP_REQUEST);
1074
1075        dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE,
1076                    DHCP_OPTION_MAX_MSG_SIZE_LEN);
1077        dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
1078
1079#if LWIP_NETIF_HOSTNAME
1080        p = (const char *) netif->hostname;
1081        if (p != NULL) {
1082            dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, strlen(p));
1083            while (*p) {
1084                dhcp_option_byte(dhcp, *p++);
1085            }
1086        }
1087#endif                          /* LWIP_NETIF_HOSTNAME */
1088
1089#if 0
1090        dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
1091        dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
1092#endif
1093
1094#if 0
1095        dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
1096        dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
1097#endif
1098        /* append DHCP message trailer */
1099        dhcp_option_trailer(dhcp);
1100
1101        pbuf_realloc(dhcp->p_out,
1102                     sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN +
1103                     dhcp->options_out_len);
1104
1105        udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
1106        udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr,
1107                      DHCP_SERVER_PORT, netif);
1108        dhcp_delete_request(netif);
1109
1110        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
1111                    ("dhcp_renew: RENEWING\n"));
1112    } else {
1113        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
1114                    ("dhcp_renew: could not allocate DHCP request\n"));
1115    }
1116    dhcp->tries++;
1117    /* back-off on retries, but to a maximum of 20 seconds */
1118    msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
1119    dhcp->request_timeout =
1120      (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
1121    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
1122                ("dhcp_renew(): set request timeout %" U16_F " msecs\n",
1123                 msecs));
1124    return result;
1125}
1126
1127/**
1128 * Rebind with a DHCP server for an existing DHCP lease.
1129 *
1130 * @param netif network interface which must rebind with a DHCP server
1131 */
1132static err_t dhcp_rebind(struct netif *netif)
1133{
1134    struct dhcp *dhcp = netif->dhcp;
1135    err_t result;
1136    u16_t msecs;
1137
1138#if LWIP_NETIF_HOSTNAME
1139    const char *p;
1140#endif                          /* LWIP_NETIF_HOSTNAME */
1141    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
1142                ("dhcp_rebind()\n"));
1143    dhcp_set_state(dhcp, DHCP_REBINDING);
1144
1145    /* create and initialize the DHCP message header */
1146    result = dhcp_create_request(netif);
1147    if (result == ERR_OK) {
1148
1149        dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE,
1150                    DHCP_OPTION_MESSAGE_TYPE_LEN);
1151        dhcp_option_byte(dhcp, DHCP_REQUEST);
1152
1153        dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE,
1154                    DHCP_OPTION_MAX_MSG_SIZE_LEN);
1155        dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
1156
1157#if LWIP_NETIF_HOSTNAME
1158        p = (const char *) netif->hostname;
1159        if (p != NULL) {
1160            dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, strlen(p));
1161            while (*p) {
1162                dhcp_option_byte(dhcp, *p++);
1163            }
1164        }
1165#endif                          /* LWIP_NETIF_HOSTNAME */
1166
1167#if 0
1168        dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
1169        dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
1170
1171        dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
1172        dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
1173#endif
1174
1175        dhcp_option_trailer(dhcp);
1176
1177        pbuf_realloc(dhcp->p_out,
1178                     sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN +
1179                     dhcp->options_out_len);
1180
1181        /* broadcast to server */
1182        udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
1183        udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST,
1184                      DHCP_SERVER_PORT, netif);
1185        dhcp_delete_request(netif);
1186        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
1187                    ("dhcp_rebind: REBINDING\n"));
1188    } else {
1189        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
1190                    ("dhcp_rebind: could not allocate DHCP request\n"));
1191    }
1192    dhcp->tries++;
1193    msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
1194    dhcp->request_timeout =
1195      (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
1196    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
1197                ("dhcp_rebind(): set request timeout %" U16_F " msecs\n",
1198                 msecs));
1199    return result;
1200}
1201
1202/**
1203 * Release a DHCP lease.
1204 *
1205 * @param netif network interface which must release its lease
1206 */
1207err_t dhcp_release(struct netif * netif)
1208{
1209    struct dhcp *dhcp = netif->dhcp;
1210    err_t result;
1211    u16_t msecs;
1212
1213    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_release()\n"));
1214
1215    /* idle DHCP client */
1216    dhcp_set_state(dhcp, DHCP_OFF);
1217    /* clean old DHCP offer */
1218    dhcp->server_ip_addr.addr = 0;
1219    dhcp->offered_ip_addr.addr = dhcp->offered_sn_mask.addr = 0;
1220    dhcp->offered_gw_addr.addr = dhcp->offered_bc_addr.addr = 0;
1221    dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind =
1222      0;
1223    dhcp->dns_count = 0;
1224
1225    /* create and initialize the DHCP message header */
1226    result = dhcp_create_request(netif);
1227    if (result == ERR_OK) {
1228        dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE,
1229                    DHCP_OPTION_MESSAGE_TYPE_LEN);
1230        dhcp_option_byte(dhcp, DHCP_RELEASE);
1231
1232        dhcp_option_trailer(dhcp);
1233
1234        pbuf_realloc(dhcp->p_out,
1235                     sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN +
1236                     dhcp->options_out_len);
1237
1238        udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
1239        udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr,
1240                      DHCP_SERVER_PORT, netif);
1241        dhcp_delete_request(netif);
1242        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
1243                    ("dhcp_release: RELEASED, DHCP_OFF\n"));
1244    } else {
1245        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
1246                    ("dhcp_release: could not allocate DHCP request\n"));
1247    }
1248    dhcp->tries++;
1249    msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
1250    dhcp->request_timeout =
1251      (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
1252    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
1253                ("dhcp_release(): set request timeout %" U16_F " msecs\n",
1254                 msecs));
1255    /* bring the interface down */
1256    netif_set_down(netif);
1257    /* remove IP address from interface */
1258    netif_set_ipaddr(netif, IP_ADDR_ANY);
1259    netif_set_gw(netif, IP_ADDR_ANY);
1260    netif_set_netmask(netif, IP_ADDR_ANY);
1261
1262    /* TODO: netif_down(netif); */
1263    return result;
1264}
1265
1266/**
1267 * Remove the DHCP client from the interface.
1268 *
1269 * @param netif The network interface to stop DHCP on
1270 */
1271void dhcp_stop(struct netif *netif)
1272{
1273    struct dhcp *dhcp = netif->dhcp;
1274
1275    LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;
1276      );
1277    /* Remove the flag that says this netif is handled by DHCP. */
1278    netif->flags &= ~NETIF_FLAG_DHCP;
1279
1280    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3, ("dhcp_stop()\n"));
1281    /* netif is DHCP configured? */
1282    if (dhcp != NULL) {
1283#if LWIP_DHCP_AUTOIP_COOP
1284        if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
1285            autoip_stop(netif);
1286            dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
1287        }
1288#endif                          /* LWIP_DHCP_AUTOIP_COOP */
1289
1290        if (dhcp->pcb != NULL) {
1291            udp_remove(dhcp->pcb);
1292            dhcp->pcb = NULL;
1293        }
1294        if (dhcp->p != NULL) {
1295            pbuf_free(dhcp->p);
1296            dhcp->p = NULL;
1297        }
1298        /* free unfolded reply */
1299        dhcp_free_reply(dhcp);
1300        mem_free((void *) dhcp);
1301        netif->dhcp = NULL;
1302    }
1303}
1304
1305/*
1306 * Set the DHCP state of a DHCP client.
1307 *
1308 * If the state changed, reset the number of tries.
1309 *
1310 * TODO: we might also want to reset the timeout here?
1311 */
1312static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state)
1313{
1314    if (new_state != dhcp->state) {
1315        dhcp->state = new_state;
1316        dhcp->tries = 0;
1317    }
1318}
1319
1320/*
1321 * Concatenate an option type and length field to the outgoing
1322 * DHCP message.
1323 *
1324 */
1325static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len)
1326{
1327    LWIP_ASSERT
1328      ("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN",
1329       dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN);
1330    dhcp->msg_out->options[dhcp->options_out_len++] = option_type;
1331    dhcp->msg_out->options[dhcp->options_out_len++] = option_len;
1332}
1333
1334/*
1335 * Concatenate a single byte to the outgoing DHCP message.
1336 *
1337 */
1338static void dhcp_option_byte(struct dhcp *dhcp, u8_t value)
1339{
1340    LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN",
1341                dhcp->options_out_len < DHCP_OPTIONS_LEN);
1342    dhcp->msg_out->options[dhcp->options_out_len++] = value;
1343}
1344
1345static void dhcp_option_short(struct dhcp *dhcp, u16_t value)
1346{
1347    LWIP_ASSERT
1348      ("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN",
1349       dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN);
1350    dhcp->msg_out->options[dhcp->options_out_len++] =
1351      (u8_t) ((value & 0xff00U) >> 8);
1352    dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU);
1353}
1354
1355static void dhcp_option_long(struct dhcp *dhcp, u32_t value)
1356{
1357    LWIP_ASSERT
1358      ("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN",
1359       dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN);
1360    dhcp->msg_out->options[dhcp->options_out_len++] =
1361      (u8_t) ((value & 0xff000000UL) >> 24);
1362    dhcp->msg_out->options[dhcp->options_out_len++] =
1363      (u8_t) ((value & 0x00ff0000UL) >> 16);
1364    dhcp->msg_out->options[dhcp->options_out_len++] =
1365      (u8_t) ((value & 0x0000ff00UL) >> 8);
1366    dhcp->msg_out->options[dhcp->options_out_len++] =
1367      (u8_t) ((value & 0x000000ffUL));
1368}
1369
1370/**
1371 * Extract the DHCP message and the DHCP options.
1372 *
1373 * Extract the DHCP message and the DHCP options, each into a contiguous
1374 * piece of memory. As a DHCP message is variable sized by its options,
1375 * and also allows overriding some fields for options, the easy approach
1376 * is to first unfold the options into a conitguous piece of memory, and
1377 * use that further on.
1378 *
1379 */
1380static err_t dhcp_unfold_reply(struct dhcp *dhcp)
1381{
1382    u16_t ret;
1383
1384    LWIP_ERROR("dhcp != NULL", (dhcp != NULL), return ERR_ARG;
1385      );
1386    LWIP_ERROR("dhcp->p != NULL", (dhcp->p != NULL), return ERR_VAL;
1387      );
1388    /* free any left-overs from previous unfolds */
1389    dhcp_free_reply(dhcp);
1390    /* options present? */
1391    if (dhcp->p->tot_len > (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN)) {
1392        dhcp->options_in_len =
1393          dhcp->p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
1394        dhcp->options_in = mem_malloc(dhcp->options_in_len);
1395        if (dhcp->options_in == NULL) {
1396            LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
1397                        ("dhcp_unfold_reply(): could not allocate dhcp->options\n"));
1398            return ERR_MEM;
1399        }
1400    }
1401    dhcp->msg_in = mem_malloc(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
1402    if (dhcp->msg_in == NULL) {
1403        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
1404                    ("dhcp_unfold_reply(): could not allocate dhcp->msg_in\n"));
1405        mem_free((void *) dhcp->options_in);
1406        dhcp->options_in = NULL;
1407        return ERR_MEM;
1408    }
1409
1410  /** copy the DHCP message without options */
1411    ret =
1412      pbuf_copy_partial(dhcp->p, dhcp->msg_in,
1413                        sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN, 0);
1414    LWIP_ASSERT("ret == sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN",
1415                ret == sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
1416    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
1417                ("dhcp_unfold_reply(): copied %zu bytes into dhcp->msg_in[]\n",
1418                 sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN));
1419
1420    if (dhcp->options_in != NULL) {
1421    /** copy the DHCP options */
1422        ret =
1423          pbuf_copy_partial(dhcp->p, dhcp->options_in, dhcp->options_in_len,
1424                            sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
1425        LWIP_ASSERT("ret == dhcp->options_in_len", ret == dhcp->options_in_len);
1426        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
1427                    ("dhcp_unfold_reply(): copied %" U16_F
1428                     " bytes to dhcp->options_in[]\n", dhcp->options_in_len));
1429    }
1430    LWIP_UNUSED_ARG(ret);
1431    return ERR_OK;
1432}
1433
1434/**
1435 * Free the incoming DHCP message including contiguous copy of
1436 * its DHCP options.
1437 *
1438 */
1439static void dhcp_free_reply(struct dhcp *dhcp)
1440{
1441    if (dhcp->msg_in != NULL) {
1442        mem_free((void *) dhcp->msg_in);
1443        dhcp->msg_in = NULL;
1444    }
1445    if (dhcp->options_in) {
1446        mem_free((void *) dhcp->options_in);
1447        dhcp->options_in = NULL;
1448        dhcp->options_in_len = 0;
1449    }
1450    LWIP_DEBUGF(DHCP_DEBUG, ("dhcp_free_reply(): free'd\n"));
1451}
1452
1453
1454/**
1455 * If an incoming DHCP message is in response to us, then trigger the state machine
1456 */
1457static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p,
1458                      struct ip_addr *addr, u16_t port)
1459{
1460    struct netif *netif = (struct netif *) arg;
1461    struct dhcp *dhcp = netif->dhcp;
1462    struct dhcp_msg *reply_msg = (struct dhcp_msg *) p->payload;
1463    u8_t *options_ptr;
1464    u8_t msg_type;
1465    u8_t i;
1466
1467    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 3,
1468                ("dhcp_recv(pbuf = %p) from DHCP server %" U16_F ".%" U16_F ".%"
1469                 U16_F ".%" U16_F " port %" U16_F "\n", (void *) p,
1470                 (u16_t) (ntohl(addr->addr) >> 24 & 0xff),
1471                 (u16_t) (ntohl(addr->addr) >> 16 & 0xff),
1472                 (u16_t) (ntohl(addr->addr) >> 8 & 0xff),
1473                 (u16_t) (ntohl(addr->addr) & 0xff), port));
1474    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
1475                ("pbuf->len = %" U16_F "\n", p->len));
1476    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
1477                ("pbuf->tot_len = %" U16_F "\n", p->tot_len));
1478    /* prevent warnings about unused arguments */
1479    LWIP_UNUSED_ARG(pcb);
1480    LWIP_UNUSED_ARG(addr);
1481    LWIP_UNUSED_ARG(port);
1482    dhcp->p = p;
1483    /* TODO: check packet length before reading them */
1484    if (reply_msg->op != DHCP_BOOTREPLY) {
1485        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1,
1486                    ("not a DHCP reply message, but type %" U16_F "\n",
1487                     (u16_t) reply_msg->op));
1488        goto free_pbuf_and_return;
1489    }
1490    /* iterate through hardware address and match against DHCP message */
1491    for (i = 0; i < netif->hwaddr_len; i++) {
1492        if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
1493            LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
1494                        ("netif->hwaddr[%" U16_F "]==%02" X16_F
1495                         " != reply_msg->chaddr[%" U16_F "]==%02" X16_F "\n",
1496                         (u16_t) i, (u16_t) netif->hwaddr[i], (u16_t) i,
1497                         (u16_t) reply_msg->chaddr[i]));
1498            goto free_pbuf_and_return;
1499        }
1500    }
1501    /* match transaction ID against what we expected */
1502    if (ntohl(reply_msg->xid) != dhcp->xid) {
1503        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
1504                    ("transaction id mismatch reply_msg->xid(%" X32_F
1505                     ")!=dhcp->xid(%" X32_F ")\n", ntohl(reply_msg->xid),
1506                     dhcp->xid));
1507        goto free_pbuf_and_return;
1508    }
1509    /* option fields could be unfold? */
1510    if (dhcp_unfold_reply(dhcp) != ERR_OK) {
1511        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
1512                    ("problem unfolding DHCP message - too short on memory?\n"));
1513        goto free_pbuf_and_return;
1514    }
1515
1516    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
1517                ("searching DHCP_OPTION_MESSAGE_TYPE\n"));
1518    /* obtain pointer to DHCP message type */
1519    options_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_MESSAGE_TYPE);
1520    if (options_ptr == NULL) {
1521        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1,
1522                    ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
1523        goto free_pbuf_and_return;
1524    }
1525
1526    /* read DHCP message type */
1527    msg_type = dhcp_get_option_byte(options_ptr + 2);
1528    /* message type is DHCP ACK? */
1529    if (msg_type == DHCP_ACK) {
1530        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("DHCP_ACK received\n"));
1531        /* in requesting state? */
1532        if (dhcp->state == DHCP_REQUESTING) {
1533            dhcp_handle_ack(netif);
1534            dhcp->request_timeout = 0;
1535#if DHCP_DOES_ARP_CHECK
1536            /* check if the acknowledged lease address is already in use */
1537            dhcp_check(netif);
1538#else
1539            /* bind interface to the acknowledged lease address */
1540            dhcp_bind(netif);
1541#endif
1542        }
1543        /* already bound to the given lease address? */
1544        else if ((dhcp->state == DHCP_REBOOTING)
1545                 || (dhcp->state == DHCP_REBINDING)
1546                 || (dhcp->state == DHCP_RENEWING)) {
1547            dhcp->request_timeout = 0;
1548            dhcp_bind(netif);
1549        }
1550    }
1551    /* received a DHCP_NAK in appropriate state? */
1552    else if ((msg_type == DHCP_NAK) &&
1553             ((dhcp->state == DHCP_REBOOTING)
1554              || (dhcp->state == DHCP_REQUESTING)
1555              || (dhcp->state == DHCP_REBINDING)
1556              || (dhcp->state == DHCP_RENEWING))) {
1557        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1, ("DHCP_NAK received\n"));
1558        dhcp->request_timeout = 0;
1559        dhcp_handle_nak(netif);
1560    }
1561    /* received a DHCP_OFFER in DHCP_SELECTING state? */
1562    else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) {
1563        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1,
1564                    ("DHCP_OFFER received in DHCP_SELECTING state\n"));
1565        dhcp->request_timeout = 0;
1566        /* remember offered lease */
1567        dhcp_handle_offer(netif);
1568    }
1569  free_pbuf_and_return:
1570    dhcp_free_reply(dhcp);
1571    pbuf_free(p);
1572    dhcp->p = NULL;
1573}
1574
1575/**
1576 * Create a DHCP request, fill in common headers
1577 *
1578 * @param netif the netif under DHCP control
1579 */
1580static err_t dhcp_create_request(struct netif *netif)
1581{
1582    struct dhcp *dhcp;
1583    u16_t i;
1584
1585#ifndef DHCP_GLOBAL_XID
1586  /** default global transaction identifier starting value (easy to match
1587   *  with a packet analyser). We simply increment for each new request.
1588   *  Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one
1589   *  at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */
1590    static u32_t xid = 0xABCD0000;
1591#else
1592    static u32_t xid;
1593    static u8_t xid_initialised = 0;
1594
1595    if (!xid_initialised) {
1596        xid = DHCP_GLOBAL_XID;
1597        xid_initialised = !xid_initialised;
1598    }
1599#endif
1600    LWIP_ERROR("dhcp_create_request: netif != NULL", (netif != NULL),
1601               return ERR_ARG;
1602      );
1603    dhcp = netif->dhcp;
1604    LWIP_ERROR("dhcp_create_request: dhcp != NULL", (dhcp != NULL),
1605               return ERR_VAL;
1606      );
1607    LWIP_ASSERT("dhcp_create_request: dhcp->p_out == NULL",
1608                dhcp->p_out == NULL);
1609    LWIP_ASSERT("dhcp_create_request: dhcp->msg_out == NULL",
1610                dhcp->msg_out == NULL);
1611    dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
1612    if (dhcp->p_out == NULL) {
1613        LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
1614                    ("dhcp_create_request(): could not allocate pbuf\n"));
1615        return ERR_MEM;
1616    }
1617    LWIP_ASSERT
1618      ("dhcp_create_request: check that first pbuf can hold struct dhcp_msg",
1619       (dhcp->p_out->len >= sizeof(struct dhcp_msg)));
1620
1621    /* reuse transaction identifier in retransmissions */
1622    if (dhcp->tries == 0)
1623        xid++;
1624    dhcp->xid = xid;
1625    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
1626                ("transaction id xid(%" X32_F ")\n", xid));
1627
1628    dhcp->msg_out = (struct dhcp_msg *) dhcp->p_out->payload;
1629
1630    dhcp->msg_out->op = DHCP_BOOTREQUEST;
1631    /* TODO: make link layer independent */
1632    dhcp->msg_out->htype = DHCP_HTYPE_ETH;
1633    /* TODO: make link layer independent */
1634    dhcp->msg_out->hlen = DHCP_HLEN_ETH;
1635    dhcp->msg_out->hops = 0;
1636    dhcp->msg_out->xid = htonl(dhcp->xid);
1637    dhcp->msg_out->secs = 0;
1638    dhcp->msg_out->flags = 0;
1639    dhcp->msg_out->ciaddr.addr = 0;
1640    if (dhcp->state == DHCP_BOUND || dhcp->state == DHCP_RENEWING
1641        || dhcp->state == DHCP_REBINDING) {
1642        dhcp->msg_out->ciaddr.addr = netif->ip_addr.addr;
1643    }
1644    dhcp->msg_out->yiaddr.addr = 0;
1645    dhcp->msg_out->siaddr.addr = 0;
1646    dhcp->msg_out->giaddr.addr = 0;
1647    for (i = 0; i < DHCP_CHADDR_LEN; i++) {
1648        /* copy netif hardware address, pad with zeroes */
1649        dhcp->msg_out->chaddr[i] =
1650          (i < netif->hwaddr_len
1651           && i < NETIF_MAX_HWADDR_LEN) ? netif->hwaddr[i] : 0 /* pad byte */ ;
1652    }
1653    for (i = 0; i < DHCP_SNAME_LEN; i++) {
1654        dhcp->msg_out->sname[i] = 0;
1655    }
1656    for (i = 0; i < DHCP_FILE_LEN; i++) {
1657        dhcp->msg_out->file[i] = 0;
1658    }
1659    dhcp->msg_out->cookie = htonl(0x63825363UL);
1660    dhcp->options_out_len = 0;
1661    /* fill options field with an incrementing array (for debugging purposes) */
1662    for (i = 0; i < DHCP_OPTIONS_LEN; i++) {
1663        dhcp->msg_out->options[i] = (u8_t) i;   /* for debugging only, no matter if truncated */
1664    }
1665    return ERR_OK;
1666}
1667
1668/**
1669 * Free previously allocated memory used to send a DHCP request.
1670 *
1671 * @param netif the netif under DHCP control
1672 */
1673static void dhcp_delete_request(struct netif *netif)
1674{
1675    struct dhcp *dhcp;
1676
1677    LWIP_ERROR("dhcp_delete_request: netif != NULL", (netif != NULL), return;
1678      );
1679    dhcp = netif->dhcp;
1680    LWIP_ERROR("dhcp_delete_request: dhcp != NULL", (dhcp != NULL), return;
1681      );
1682    LWIP_ASSERT("dhcp_delete_request: dhcp->p_out != NULL",
1683                dhcp->p_out != NULL);
1684    LWIP_ASSERT("dhcp_delete_request: dhcp->msg_out != NULL",
1685                dhcp->msg_out != NULL);
1686    if (dhcp->p_out != NULL) {
1687        pbuf_free(dhcp->p_out);
1688    }
1689    dhcp->p_out = NULL;
1690    dhcp->msg_out = NULL;
1691}
1692
1693/**
1694 * Add a DHCP message trailer
1695 *
1696 * Adds the END option to the DHCP message, and if
1697 * necessary, up to three padding bytes.
1698 *
1699 * @param dhcp DHCP state structure
1700 */
1701static void dhcp_option_trailer(struct dhcp *dhcp)
1702{
1703    LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;
1704      );
1705    LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n",
1706                dhcp->msg_out != NULL);
1707    LWIP_ASSERT
1708      ("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n",
1709       dhcp->options_out_len < DHCP_OPTIONS_LEN);
1710    dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
1711    /* packet is too small, or not 4 byte aligned? */
1712    while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN)
1713           || (dhcp->options_out_len & 3)) {
1714        /* 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)); */
1715        LWIP_ASSERT
1716          ("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n",
1717           dhcp->options_out_len < DHCP_OPTIONS_LEN);
1718        /* add a fill/padding byte */
1719        dhcp->msg_out->options[dhcp->options_out_len++] = 0;
1720    }
1721}
1722
1723/**
1724 * Find the offset of a DHCP option inside the DHCP message.
1725 *
1726 * @param dhcp DHCP client
1727 * @param option_type
1728 *
1729 * @return a byte offset into the UDP message where the option was found, or
1730 * zero if the given option was not found.
1731 */
1732static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
1733{
1734    u8_t overload = DHCP_OVERLOAD_NONE;
1735
1736    /* options available? */
1737    if ((dhcp->options_in != NULL) && (dhcp->options_in_len > 0)) {
1738        /* start with options field */
1739        u8_t *options = (u8_t *) dhcp->options_in;
1740        u16_t offset = 0;
1741
1742        /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
1743        while ((offset < dhcp->options_in_len)
1744               && (options[offset] != DHCP_OPTION_END)) {
1745            /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
1746            /* are the sname and/or file field overloaded with options? */
1747            if (options[offset] == DHCP_OPTION_OVERLOAD) {
1748                LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 2,
1749                            ("overloaded message detected\n"));
1750                /* skip option type and length */
1751                offset += 2;
1752                overload = options[offset++];
1753            }
1754            /* requested option found */
1755            else if (options[offset] == option_type) {
1756                LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
1757                            ("option found at offset %" U16_F " in options\n",
1758                             offset));
1759                return &options[offset];
1760                /* skip option */
1761            } else {
1762                LWIP_DEBUGF(DHCP_DEBUG,
1763                            ("skipping option %" U16_F " in options\n",
1764                             options[offset]));
1765                /* skip option type */
1766                offset++;
1767                /* skip option length, and then length bytes */
1768                offset += 1 + options[offset];
1769            }
1770        }
1771        /* is this an overloaded message? */
1772        if (overload != DHCP_OVERLOAD_NONE) {
1773            u16_t field_len;
1774
1775            if (overload == DHCP_OVERLOAD_FILE) {
1776                LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1,
1777                            ("overloaded file field\n"));
1778                options = (u8_t *) & dhcp->msg_in->file;
1779                field_len = DHCP_FILE_LEN;
1780            } else if (overload == DHCP_OVERLOAD_SNAME) {
1781                LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1,
1782                            ("overloaded sname field\n"));
1783                options = (u8_t *) & dhcp->msg_in->sname;
1784                field_len = DHCP_SNAME_LEN;
1785                /* TODO: check if else if () is necessary */
1786            } else {
1787                LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | 1,
1788                            ("overloaded sname and file field\n"));
1789                options = (u8_t *) & dhcp->msg_in->sname;
1790                field_len = DHCP_FILE_LEN + DHCP_SNAME_LEN;
1791            }
1792            offset = 0;
1793
1794            /* at least 1 byte to read and no end marker */
1795            while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) {
1796                if (options[offset] == option_type) {
1797                    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
1798                                ("option found at offset=%" U16_F "\n",
1799                                 offset));
1800                    return &options[offset];
1801                    /* skip option */
1802                } else {
1803                    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
1804                                ("skipping option %" U16_F "\n",
1805                                 options[offset]));
1806                    /* skip option type */
1807                    offset++;
1808                    offset += 1 + options[offset];
1809                }
1810            }
1811        }
1812    }
1813    return NULL;
1814}
1815
1816/**
1817 * Return the byte of DHCP option data.
1818 *
1819 * @param client DHCP client.
1820 * @param ptr pointer obtained by dhcp_get_option_ptr().
1821 *
1822 * @return byte value at the given address.
1823 */
1824static u8_t dhcp_get_option_byte(u8_t * ptr)
1825{
1826    LWIP_DEBUGF(DHCP_DEBUG, ("option byte value=%" U16_F "\n", (u16_t) (*ptr)));
1827    return *ptr;
1828}
1829
1830#if 0                           /* currently unused */
1831/**
1832 * Return the 16-bit value of DHCP option data.
1833 *
1834 * @param client DHCP client.
1835 * @param ptr pointer obtained by dhcp_get_option_ptr().
1836 *
1837 * @return byte value at the given address.
1838 */
1839static u16_t dhcp_get_option_short(u8_t * ptr)
1840{
1841    u16_t value;
1842
1843    value = *ptr++ << 8;
1844    value |= *ptr;
1845    LWIP_DEBUGF(DHCP_DEBUG, ("option short value=%" U16_F "\n", value));
1846    return value;
1847}
1848#endif
1849
1850/**
1851 * Return the 32-bit value of DHCP option data.
1852 *
1853 * @param client DHCP client.
1854 * @param ptr pointer obtained by dhcp_get_option_ptr().
1855 *
1856 * @return byte value at the given address.
1857 */
1858static u32_t dhcp_get_option_long(u8_t * ptr)
1859{
1860    u32_t value;
1861
1862    value = (u32_t) (*ptr++) << 24;
1863    value |= (u32_t) (*ptr++) << 16;
1864    value |= (u32_t) (*ptr++) << 8;
1865    value |= (u32_t) (*ptr++);
1866    LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%" U32_F "\n", value));
1867    return value;
1868}
1869
1870#endif                          /* LWIP_DHCP */
1871