ReactOS 0.4.15-dev-7953-g1f49173
dhcp.c
Go to the documentation of this file.
1
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 * - Support for interfaces other than Ethernet (SLIP, PPP, ...)
47 *
48 * Please coordinate changes and requests with Leon Woestenberg
49 * <leon.woestenberg@gmx.net>
50 *
51 * Integration with your code:
52 *
53 * In lwip/dhcp.h
54 * #define DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute)
55 * #define DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer)
56 *
57 * Then have your application call dhcp_coarse_tmr() and
58 * dhcp_fine_tmr() on the defined intervals.
59 *
60 * dhcp_start(struct netif *netif);
61 * starts a DHCP client instance which configures the interface by
62 * obtaining an IP address lease and maintaining it.
63 *
64 * Use dhcp_release(netif) to end the lease and use dhcp_stop(netif)
65 * to remove the DHCP client.
66 *
67 */
68
69#include "lwip/opt.h"
70
71#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */
72
73#include "lwip/stats.h"
74#include "lwip/mem.h"
75#include "lwip/udp.h"
76#include "lwip/ip_addr.h"
77#include "lwip/netif.h"
78#include "lwip/def.h"
79#include "lwip/dhcp.h"
80#include "lwip/autoip.h"
81#include "lwip/dns.h"
82#include "netif/etharp.h"
83
84#include <string.h>
85
89#ifndef DHCP_CREATE_RAND_XID
90#define DHCP_CREATE_RAND_XID 1
91#endif
92
98#ifdef DHCP_GLOBAL_XID_HEADER
99#include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */
100#endif
101
104#define DHCP_MAX_MSG_LEN(netif) (netif->mtu)
105#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576
107#define DHCP_MIN_REPLY_LEN 44
108
109#define REBOOT_TRIES 2
110
116#define DHCP_OPTION_IDX_OVERLOAD 0
117#define DHCP_OPTION_IDX_MSG_TYPE 1
118#define DHCP_OPTION_IDX_SERVER_ID 2
119#define DHCP_OPTION_IDX_LEASE_TIME 3
120#define DHCP_OPTION_IDX_T1 4
121#define DHCP_OPTION_IDX_T2 5
122#define DHCP_OPTION_IDX_SUBNET_MASK 6
123#define DHCP_OPTION_IDX_ROUTER 7
124#define DHCP_OPTION_IDX_DNS_SERVER 8
125#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS)
126
129u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX];
133u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX];
134
135#ifdef DHCP_GLOBAL_XID
136static u32_t xid;
137static u8_t xid_initialised;
138#endif /* DHCP_GLOBAL_XID */
139
140#define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0)
141#define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1)
142#define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0)
143#define dhcp_clear_all_options(dhcp) (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given)))
144#define dhcp_get_option_value(dhcp, idx) (dhcp_rx_options_val[idx])
145#define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val))
146
147
148/* DHCP client state machine functions */
149static err_t dhcp_discover(struct netif *netif);
150static err_t dhcp_select(struct netif *netif);
151static void dhcp_bind(struct netif *netif);
152#if DHCP_DOES_ARP_CHECK
153static err_t dhcp_decline(struct netif *netif);
154#endif /* DHCP_DOES_ARP_CHECK */
155static err_t dhcp_rebind(struct netif *netif);
156static err_t dhcp_reboot(struct netif *netif);
157static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
158
159/* receive, unfold, parse and free incoming messages */
160static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
161
162/* set the DHCP timers */
163static void dhcp_timeout(struct netif *netif);
164static void dhcp_t1_timeout(struct netif *netif);
165static void dhcp_t2_timeout(struct netif *netif);
166
167/* build outgoing messages */
168/* create a DHCP message, fill in common headers */
169static err_t dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type);
170/* free a DHCP request */
171static void dhcp_delete_msg(struct dhcp *dhcp);
172/* add a DHCP option (type, then length in bytes) */
173static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len);
174/* add option values */
175static void dhcp_option_byte(struct dhcp *dhcp, u8_t value);
176static void dhcp_option_short(struct dhcp *dhcp, u16_t value);
177static void dhcp_option_long(struct dhcp *dhcp, u32_t value);
178#if LWIP_NETIF_HOSTNAME
179static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif);
180#endif /* LWIP_NETIF_HOSTNAME */
181/* always add the DHCP options trailer to end and pad */
182static void dhcp_option_trailer(struct dhcp *dhcp);
183
196static void
197dhcp_handle_nak(struct netif *netif)
198{
199 struct dhcp *dhcp = netif->dhcp;
200 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
201 (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
202 /* Set the interface down since the address must no longer be used, as per RFC2131 */
204 /* remove IP address from interface */
208 /* Change to a defined state */
209 dhcp_set_state(dhcp, DHCP_BACKING_OFF);
210 /* We can immediately restart discovery */
211 dhcp_discover(netif);
212}
213
214#if DHCP_DOES_ARP_CHECK
224static void
225dhcp_check(struct netif *netif)
226{
227 struct dhcp *dhcp = netif->dhcp;
229 u16_t msecs;
230 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
231 (s16_t)netif->name[1]));
232 dhcp_set_state(dhcp, DHCP_CHECKING);
233 /* create an ARP query for the offered IP address, expecting that no host
234 responds, as the IP address should not be in use. */
235 result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
236 if (result != ERR_OK) {
237 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n"));
238 }
239 dhcp->tries++;
240 msecs = 500;
241 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
242 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs));
243}
244#endif /* DHCP_DOES_ARP_CHECK */
245
251static void
252dhcp_handle_offer(struct netif *netif)
253{
254 struct dhcp *dhcp = netif->dhcp;
255 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
256 (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
257 /* obtain the server address */
258 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) {
259 ip4_addr_set_u32(&dhcp->server_ip_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID)));
260 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n",
261 ip4_addr_get_u32(&dhcp->server_ip_addr)));
262 /* remember offered address */
263 ip_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr);
264 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n",
265 ip4_addr_get_u32(&dhcp->offered_ip_addr)));
266
267 dhcp_select(netif);
268 } else {
270 ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void*)netif));
271 }
272}
273
282static err_t
283dhcp_select(struct netif *netif)
284{
285 struct dhcp *dhcp = netif->dhcp;
287 u16_t msecs;
288
289 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
290 dhcp_set_state(dhcp, DHCP_REQUESTING);
291
292 /* create and initialize the DHCP message header */
293 result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
294 if (result == ERR_OK) {
295 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
296 dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
297
298 /* MUST request the offered IP address */
299 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
300 dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
301
302 dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
303 dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->server_ip_addr)));
304
305 dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
306 dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
307 dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
308 dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
309 dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
310
311#if LWIP_NETIF_HOSTNAME
312 dhcp_option_hostname(dhcp, netif);
313#endif /* LWIP_NETIF_HOSTNAME */
314
315 dhcp_option_trailer(dhcp);
316 /* shrink the pbuf to the actual content length */
317 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
318
319 /* send broadcast to any DHCP server */
320 udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
321 dhcp_delete_msg(dhcp);
322 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n"));
323 } else {
324 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n"));
325 }
326 dhcp->tries++;
327 msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
328 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
329 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs));
330 return result;
331}
332
336void
337dhcp_coarse_tmr()
338{
339 struct netif *netif = netif_list;
340 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n"));
341 /* iterate through all network interfaces */
342 while (netif != NULL) {
343 /* only act on DHCP configured interfaces */
344 if (netif->dhcp != NULL) {
345 /* timer is active (non zero), and triggers (zeroes) now? */
346 if (netif->dhcp->t2_timeout-- == 1) {
347 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n"));
348 /* this clients' rebind timeout triggered */
349 dhcp_t2_timeout(netif);
350 /* timer is active (non zero), and triggers (zeroes) now */
351 } else if (netif->dhcp->t1_timeout-- == 1) {
352 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n"));
353 /* this clients' renewal timeout triggered */
354 dhcp_t1_timeout(netif);
355 }
356 }
357 /* proceed to next netif */
358 netif = netif->next;
359 }
360}
361
368void
369dhcp_fine_tmr()
370{
371 struct netif *netif = netif_list;
372 /* loop through netif's */
373 while (netif != NULL) {
374 /* only act on DHCP configured interfaces */
375 if (netif->dhcp != NULL) {
376 /* timer is active (non zero), and is about to trigger now */
377 if (netif->dhcp->request_timeout > 1) {
378 netif->dhcp->request_timeout--;
379 }
380 else if (netif->dhcp->request_timeout == 1) {
381 netif->dhcp->request_timeout--;
382 /* { netif->dhcp->request_timeout == 0 } */
383 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
384 /* this client's request timeout triggered */
385 dhcp_timeout(netif);
386 }
387 }
388 /* proceed to next network interface */
389 netif = netif->next;
390 }
391}
392
401static void
402dhcp_timeout(struct netif *netif)
403{
404 struct dhcp *dhcp = netif->dhcp;
405 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n"));
406 /* back-off period has passed, or server selection timed out */
407 if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) {
408 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n"));
409 dhcp_discover(netif);
410 /* receiving the requested lease timed out */
411 } else if (dhcp->state == DHCP_REQUESTING) {
412 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n"));
413 if (dhcp->tries <= 5) {
414 dhcp_select(netif);
415 } else {
416 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n"));
417 dhcp_release(netif);
418 dhcp_discover(netif);
419 }
420#if DHCP_DOES_ARP_CHECK
421 /* received no ARP reply for the offered address (which is good) */
422 } else if (dhcp->state == DHCP_CHECKING) {
423 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n"));
424 if (dhcp->tries <= 1) {
425 dhcp_check(netif);
426 /* no ARP replies on the offered address,
427 looks like the IP address is indeed free */
428 } else {
429 /* bind the interface to the offered address */
430 dhcp_bind(netif);
431 }
432#endif /* DHCP_DOES_ARP_CHECK */
433 }
434 /* did not get response to renew request? */
435 else if (dhcp->state == DHCP_RENEWING) {
436 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RENEWING, DHCP request timed out\n"));
437 /* just retry renewal */
438 /* note that the rebind timer will eventually time-out if renew does not work */
439 dhcp_renew(netif);
440 /* did not get response to rebind request? */
441 } else if (dhcp->state == DHCP_REBINDING) {
442 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REBINDING, DHCP request timed out\n"));
443 if (dhcp->tries <= 8) {
444 dhcp_rebind(netif);
445 } else {
446 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RELEASING, DISCOVERING\n"));
447 dhcp_release(netif);
448 dhcp_discover(netif);
449 }
450 } else if (dhcp->state == DHCP_REBOOTING) {
451 if (dhcp->tries < REBOOT_TRIES) {
452 dhcp_reboot(netif);
453 } else {
454 dhcp_discover(netif);
455 }
456 }
457}
458
464static void
465dhcp_t1_timeout(struct netif *netif)
466{
467 struct dhcp *dhcp = netif->dhcp;
468 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n"));
469 if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) ||
470 (dhcp->state == DHCP_RENEWING)) {
471 /* just retry to renew - note that the rebind timer (t2) will
472 * eventually time-out if renew tries fail. */
474 ("dhcp_t1_timeout(): must renew\n"));
475 /* This slightly different to RFC2131: DHCPREQUEST will be sent from state
476 DHCP_RENEWING, not DHCP_BOUND */
477 dhcp_renew(netif);
478 }
479}
480
486static void
487dhcp_t2_timeout(struct netif *netif)
488{
489 struct dhcp *dhcp = netif->dhcp;
490 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n"));
491 if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) ||
492 (dhcp->state == DHCP_RENEWING)) {
493 /* just retry to rebind */
495 ("dhcp_t2_timeout(): must rebind\n"));
496 /* This slightly different to RFC2131: DHCPREQUEST will be sent from state
497 DHCP_REBINDING, not DHCP_BOUND */
498 dhcp_rebind(netif);
499 }
500}
501
507static void
508dhcp_handle_ack(struct netif *netif)
509{
510 struct dhcp *dhcp = netif->dhcp;
511#if LWIP_DNS
512 u8_t n;
513#endif /* LWIP_DNS */
514
515 /* clear options we might not get from the ACK */
516 ip_addr_set_zero(&dhcp->offered_sn_mask);
517 ip_addr_set_zero(&dhcp->offered_gw_addr);
518#if LWIP_DHCP_BOOTP_FILE
519 ip_addr_set_zero(&dhcp->offered_si_addr);
520#endif /* LWIP_DHCP_BOOTP_FILE */
521
522 /* lease time given? */
523 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) {
524 /* remember offered lease time */
525 dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME);
526 }
527 /* renewal period given? */
528 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) {
529 /* remember given renewal period */
530 dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1);
531 } else {
532 /* calculate safe periods for renewal */
533 dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2;
534 }
535
536 /* renewal period given? */
537 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) {
538 /* remember given rebind period */
539 dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2);
540 } else {
541 /* calculate safe periods for rebinding */
542 dhcp->offered_t2_rebind = dhcp->offered_t0_lease;
543 }
544
545 /* (y)our internet address */
546 ip_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr);
547
548#if LWIP_DHCP_BOOTP_FILE
549 /* copy boot server address,
550 boot file name copied in dhcp_parse_reply if not overloaded */
551 ip_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr);
552#endif /* LWIP_DHCP_BOOTP_FILE */
553
554 /* subnet mask given? */
555 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) {
556 /* remember given subnet mask */
557 ip4_addr_set_u32(&dhcp->offered_sn_mask, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)));
558 dhcp->subnet_mask_given = 1;
559 } else {
560 dhcp->subnet_mask_given = 0;
561 }
562
563 /* gateway router */
564 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) {
565 ip4_addr_set_u32(&dhcp->offered_gw_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER)));
566 }
567
568#if LWIP_DNS
569 /* DNS servers */
570 n = 0;
571 while(dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n) && (n < DNS_MAX_SERVERS)) {
572 ip_addr_t dns_addr;
573 ip4_addr_set_u32(&dns_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
574 dns_setserver(n, &dns_addr);
575 n++;
576 }
577#endif /* LWIP_DNS */
578}
579
586void
587dhcp_set_struct(struct netif *netif, struct dhcp *dhcp)
588{
589 LWIP_ASSERT("netif != NULL", netif != NULL);
590 LWIP_ASSERT("dhcp != NULL", dhcp != NULL);
591 LWIP_ASSERT("netif already has a struct dhcp set", netif->dhcp == NULL);
592
593 /* clear data structure */
594 memset(dhcp, 0, sizeof(struct dhcp));
595 /* dhcp_set_state(&dhcp, DHCP_OFF); */
596 netif->dhcp = dhcp;
597}
598
606void dhcp_cleanup(struct netif *netif)
607{
608 LWIP_ASSERT("netif != NULL", netif != NULL);
609
610 if (netif->dhcp != NULL) {
611 mem_free(netif->dhcp);
612 netif->dhcp = NULL;
613 }
614}
615
628err_t
629dhcp_start(struct netif *netif)
630{
631 struct dhcp *dhcp;
633
634 LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
635 dhcp = netif->dhcp;
636 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));
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 hwtype of the netif */
642 if ((netif->flags & NETIF_FLAG_ETHARP) == 0) {
643 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): No ETHARP netif\n"));
644 return ERR_ARG;
645 }
646
647 /* check MTU of the netif */
648 if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) {
649 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n"));
650 return ERR_MEM;
651 }
652
653 /* no DHCP client attached yet? */
654 if (dhcp == NULL) {
655 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
656 dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp));
657 if (dhcp == NULL) {
658 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
659 return ERR_MEM;
660 }
661 /* store this dhcp client in the netif */
662 netif->dhcp = dhcp;
663 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp"));
664 /* already has DHCP client attached */
665 } else {
666 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n"));
667 if (dhcp->pcb != NULL) {
668 udp_remove(dhcp->pcb);
669 }
670 LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL);
671 LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL );
672 }
673
674 /* clear data structure */
675 memset(dhcp, 0, sizeof(struct dhcp));
676 /* dhcp_set_state(&dhcp, DHCP_OFF); */
677 /* allocate UDP PCB */
678 dhcp->pcb = udp_new();
679 if (dhcp->pcb == NULL) {
680 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not obtain pcb\n"));
681 return ERR_MEM;
682 }
684 /* set up local and remote port for the pcb */
685 udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
686 udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
687 /* set up the recv callback and argument */
688 udp_recv(dhcp->pcb, dhcp_recv, netif);
689 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
690 /* (re)start the DHCP negotiation */
691 result = dhcp_discover(netif);
692 if (result != ERR_OK) {
693 /* free resources allocated above */
694 dhcp_stop(netif);
695 return ERR_MEM;
696 }
697 /* Set the flag that says this netif is handled by DHCP. */
699 return result;
700}
701
711void
712dhcp_inform(struct netif *netif)
713{
714 struct dhcp dhcp;
716 struct udp_pcb *pcb;
717
718 LWIP_ERROR("netif != NULL", (netif != NULL), return;);
719
720 memset(&dhcp, 0, sizeof(struct dhcp));
721 dhcp_set_state(&dhcp, DHCP_INFORM);
722
723 if ((netif->dhcp != NULL) && (netif->dhcp->pcb != NULL)) {
724 /* re-use existing pcb */
725 pcb = netif->dhcp->pcb;
726 } else {
727 pcb = udp_new();
728 if (pcb == NULL) {
729 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not obtain pcb"));
730 return;
731 }
732 dhcp.pcb = pcb;
734 udp_bind(dhcp.pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
735 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n"));
736 }
737 /* create and initialize the DHCP message header */
738 result = dhcp_create_msg(netif, &dhcp, DHCP_INFORM);
739 if (result == ERR_OK) {
740 dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
741 dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif));
742
743 dhcp_option_trailer(&dhcp);
744
745 pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len);
746
747 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n"));
748 udp_sendto_if(pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
749 dhcp_delete_msg(&dhcp);
750 } else {
751 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n"));
752 }
753
754 if (dhcp.pcb != NULL) {
755 /* otherwise, the existing pcb was used */
756 udp_remove(dhcp.pcb);
757 }
758}
759
765void
766dhcp_network_changed(struct netif *netif)
767{
768 struct dhcp *dhcp = netif->dhcp;
769 if (!dhcp)
770 return;
771 switch (dhcp->state) {
772 case DHCP_REBINDING:
773 case DHCP_RENEWING:
774 case DHCP_BOUND:
775 case DHCP_REBOOTING:
777 dhcp->tries = 0;
778 dhcp_reboot(netif);
779 break;
780 case DHCP_OFF:
781 /* stay off */
782 break;
783 default:
784 dhcp->tries = 0;
785#if LWIP_DHCP_AUTOIP_COOP
786 if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
787 autoip_stop(netif);
788 dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
789 }
790#endif /* LWIP_DHCP_AUTOIP_COOP */
791 dhcp_discover(netif);
792 break;
793 }
794}
795
796#if DHCP_DOES_ARP_CHECK
803void dhcp_arp_reply(struct netif *netif, ip_addr_t *addr)
804{
805 LWIP_ERROR("netif != NULL", (netif != NULL), return;);
806 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n"));
807 /* is a DHCP client doing an ARP check? */
808 if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
809 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n",
811 /* did a host respond with the address we
812 were offered by the DHCP server? */
813 if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
814 /* we will not accept the offered address */
816 ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
817 dhcp_decline(netif);
818 }
819 }
820}
821
831static err_t
832dhcp_decline(struct netif *netif)
833{
834 struct dhcp *dhcp = netif->dhcp;
836 u16_t msecs;
837 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n"));
838 dhcp_set_state(dhcp, DHCP_BACKING_OFF);
839 /* create and initialize the DHCP message header */
840 result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE);
841 if (result == ERR_OK) {
842 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
843 dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
844
845 dhcp_option_trailer(dhcp);
846 /* resize pbuf to reflect true size of options */
847 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
848
849 /* per section 4.4.4, broadcast DECLINE messages */
850 udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
851 dhcp_delete_msg(dhcp);
852 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
853 } else {
855 ("dhcp_decline: could not allocate DHCP request\n"));
856 }
857 dhcp->tries++;
858 msecs = 10*1000;
859 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
860 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs));
861 return result;
862}
863#endif /* DHCP_DOES_ARP_CHECK */
864
865
871static err_t
872dhcp_discover(struct netif *netif)
873{
874 struct dhcp *dhcp = netif->dhcp;
876 u16_t msecs;
877 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n"));
878 ip_addr_set_any(&dhcp->offered_ip_addr);
879 dhcp_set_state(dhcp, DHCP_SELECTING);
880 /* create and initialize the DHCP message header */
881 result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER);
882 if (result == ERR_OK) {
883 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n"));
884
885 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
886 dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
887
888 dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
889 dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
890 dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
891 dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
892 dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
893
894 dhcp_option_trailer(dhcp);
895
896 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n"));
897 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
898
899 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
900 udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
901 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
902 dhcp_delete_msg(dhcp);
903 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
904 } else {
905 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n"));
906 }
907 dhcp->tries++;
908#if LWIP_DHCP_AUTOIP_COOP
909 if(dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) {
910 dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON;
911 autoip_start(netif);
912 }
913#endif /* LWIP_DHCP_AUTOIP_COOP */
914 msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
915 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
916 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs));
917 return result;
918}
919
920
926static void
927dhcp_bind(struct netif *netif)
928{
930 struct dhcp *dhcp;
931 ip_addr_t sn_mask, gw_addr;
932 LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;);
933 dhcp = netif->dhcp;
934 LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;);
935 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
936
937 /* temporary DHCP lease? */
938 if (dhcp->offered_t1_renew != 0xffffffffUL) {
939 /* set renewal period timer */
940 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew));
941 timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
942 if(timeout > 0xffff) {
943 timeout = 0xffff;
944 }
945 dhcp->t1_timeout = (u16_t)timeout;
946 if (dhcp->t1_timeout == 0) {
947 dhcp->t1_timeout = 1;
948 }
949 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000));
950 }
951 /* set renewal period timer */
952 if (dhcp->offered_t2_rebind != 0xffffffffUL) {
953 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind));
954 timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
955 if(timeout > 0xffff) {
956 timeout = 0xffff;
957 }
958 dhcp->t2_timeout = (u16_t)timeout;
959 if (dhcp->t2_timeout == 0) {
960 dhcp->t2_timeout = 1;
961 }
962 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000));
963 }
964
965 /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */
966 if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) {
967 dhcp->t1_timeout = 0;
968 }
969
970 if (dhcp->subnet_mask_given) {
971 /* copy offered network mask */
972 ip_addr_copy(sn_mask, dhcp->offered_sn_mask);
973 } else {
974 /* subnet mask not given, choose a safe subnet mask given the network class */
975 u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr);
976 if (first_octet <= 127) {
977 ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL));
978 } else if (first_octet >= 192) {
979 ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL));
980 } else {
981 ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL));
982 }
983 }
984
985 ip_addr_copy(gw_addr, dhcp->offered_gw_addr);
986 /* gateway address not given? */
987 if (ip_addr_isany(&gw_addr)) {
988 /* copy network address */
989 ip_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask);
990 /* use first host address on network as gateway */
991 ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL));
992 }
993
994#if LWIP_DHCP_AUTOIP_COOP
995 if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
996 autoip_stop(netif);
997 dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
998 }
999#endif /* LWIP_DHCP_AUTOIP_COOP */
1000
1001 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n",
1002 ip4_addr_get_u32(&dhcp->offered_ip_addr)));
1003 netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
1004 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n",
1005 ip4_addr_get_u32(&sn_mask)));
1006 netif_set_netmask(netif, &sn_mask);
1007 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n",
1008 ip4_addr_get_u32(&gw_addr)));
1009 netif_set_gw(netif, &gw_addr);
1010 /* bring the interface up */
1012 /* netif is now bound to DHCP leased address */
1013 dhcp_set_state(dhcp, DHCP_BOUND);
1014}
1015
1021err_t
1022dhcp_renew(struct netif *netif)
1023{
1024 struct dhcp *dhcp = netif->dhcp;
1025 err_t result;
1026 u16_t msecs;
1027 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n"));
1028 dhcp_set_state(dhcp, DHCP_RENEWING);
1029
1030 /* create and initialize the DHCP message header */
1031 result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
1032 if (result == ERR_OK) {
1033 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
1034 dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
1035
1036#if 0
1037 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
1038 dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
1039#endif
1040
1041#if 0
1042 dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
1043 dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
1044#endif
1045
1046#if LWIP_NETIF_HOSTNAME
1047 dhcp_option_hostname(dhcp, netif);
1048#endif /* LWIP_NETIF_HOSTNAME */
1049
1050 /* append DHCP message trailer */
1051 dhcp_option_trailer(dhcp);
1052
1053 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
1054
1055 udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
1056 dhcp_delete_msg(dhcp);
1057
1058 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n"));
1059 } else {
1060 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n"));
1061 }
1062 dhcp->tries++;
1063 /* back-off on retries, but to a maximum of 20 seconds */
1064 msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
1065 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
1066 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs));
1067 return result;
1068}
1069
1075static err_t
1076dhcp_rebind(struct netif *netif)
1077{
1078 struct dhcp *dhcp = netif->dhcp;
1079 err_t result;
1080 u16_t msecs;
1081 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n"));
1082 dhcp_set_state(dhcp, DHCP_REBINDING);
1083
1084 /* create and initialize the DHCP message header */
1085 result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
1086 if (result == ERR_OK) {
1087 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
1088 dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
1089
1090#if LWIP_NETIF_HOSTNAME
1091 dhcp_option_hostname(dhcp, netif);
1092#endif /* LWIP_NETIF_HOSTNAME */
1093
1094#if 0
1095 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
1096 dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
1097
1098 dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
1099 dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
1100#endif
1101
1102 dhcp_option_trailer(dhcp);
1103
1104 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
1105
1106 /* broadcast to server */
1107 udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
1108 dhcp_delete_msg(dhcp);
1109 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n"));
1110 } else {
1111 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n"));
1112 }
1113 dhcp->tries++;
1114 msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
1115 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
1116 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs));
1117 return result;
1118}
1119
1125static err_t
1126dhcp_reboot(struct netif *netif)
1127{
1128 struct dhcp *dhcp = netif->dhcp;
1129 err_t result;
1130 u16_t msecs;
1131 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n"));
1132 dhcp_set_state(dhcp, DHCP_REBOOTING);
1133
1134 /* create and initialize the DHCP message header */
1135 result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
1136 if (result == ERR_OK) {
1137 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
1138 dhcp_option_short(dhcp, 576);
1139
1140 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
1141 dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
1142
1143 dhcp_option_trailer(dhcp);
1144
1145 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
1146
1147 /* broadcast to server */
1148 udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
1149 dhcp_delete_msg(dhcp);
1150 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n"));
1151 } else {
1152 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n"));
1153 }
1154 dhcp->tries++;
1155 msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
1156 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
1157 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs));
1158 return result;
1159}
1160
1161
1167err_t
1168dhcp_release(struct netif *netif)
1169{
1170 struct dhcp *dhcp = netif->dhcp;
1171 err_t result;
1172 u16_t msecs;
1173 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n"));
1174
1175 /* idle DHCP client */
1176 dhcp_set_state(dhcp, DHCP_OFF);
1177 /* clean old DHCP offer */
1178 ip_addr_set_zero(&dhcp->server_ip_addr);
1179 ip_addr_set_zero(&dhcp->offered_ip_addr);
1180 ip_addr_set_zero(&dhcp->offered_sn_mask);
1181 ip_addr_set_zero(&dhcp->offered_gw_addr);
1182#if LWIP_DHCP_BOOTP_FILE
1183 ip_addr_set_zero(&dhcp->offered_si_addr);
1184#endif /* LWIP_DHCP_BOOTP_FILE */
1185 dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0;
1186
1187 /* create and initialize the DHCP message header */
1188 result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE);
1189 if (result == ERR_OK) {
1190 dhcp_option_trailer(dhcp);
1191
1192 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
1193
1194 udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
1195 dhcp_delete_msg(dhcp);
1196 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n"));
1197 } else {
1198 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n"));
1199 }
1200 dhcp->tries++;
1201 msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
1202 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
1203 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs));
1204 /* bring the interface down */
1206 /* remove IP address from interface */
1210
1211 return result;
1212}
1213
1219void
1220dhcp_stop(struct netif *netif)
1221{
1222 struct dhcp *dhcp;
1223 LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;);
1224 dhcp = netif->dhcp;
1225 /* Remove the flag that says this netif is handled by DHCP. */
1226 netif->flags &= ~NETIF_FLAG_DHCP;
1227
1228 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n"));
1229 /* netif is DHCP configured? */
1230 if (dhcp != NULL) {
1231#if LWIP_DHCP_AUTOIP_COOP
1232 if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
1233 autoip_stop(netif);
1234 dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
1235 }
1236#endif /* LWIP_DHCP_AUTOIP_COOP */
1237
1238 if (dhcp->pcb != NULL) {
1239 udp_remove(dhcp->pcb);
1240 dhcp->pcb = NULL;
1241 }
1242 LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL);
1243 dhcp_set_state(dhcp, DHCP_OFF);
1244 }
1245}
1246
1247/*
1248 * Set the DHCP state of a DHCP client.
1249 *
1250 * If the state changed, reset the number of tries.
1251 */
1252static void
1253dhcp_set_state(struct dhcp *dhcp, u8_t new_state)
1254{
1255 if (new_state != dhcp->state) {
1256 dhcp->state = new_state;
1257 dhcp->tries = 0;
1258 dhcp->request_timeout = 0;
1259 }
1260}
1261
1262/*
1263 * Concatenate an option type and length field to the outgoing
1264 * DHCP message.
1265 *
1266 */
1267static void
1268dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len)
1269{
1270 LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN);
1271 dhcp->msg_out->options[dhcp->options_out_len++] = option_type;
1272 dhcp->msg_out->options[dhcp->options_out_len++] = option_len;
1273}
1274/*
1275 * Concatenate a single byte to the outgoing DHCP message.
1276 *
1277 */
1278static void
1279dhcp_option_byte(struct dhcp *dhcp, u8_t value)
1280{
1281 LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN);
1282 dhcp->msg_out->options[dhcp->options_out_len++] = value;
1283}
1284
1285static void
1286dhcp_option_short(struct dhcp *dhcp, u16_t value)
1287{
1288 LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN);
1289 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8);
1290 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU);
1291}
1292
1293static void
1294dhcp_option_long(struct dhcp *dhcp, u32_t value)
1295{
1296 LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN);
1297 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24);
1298 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16);
1299 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8);
1300 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL));
1301}
1302
1303#if LWIP_NETIF_HOSTNAME
1304static void
1305dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif)
1306{
1307 if (netif->hostname != NULL) {
1308 size_t namelen = strlen(netif->hostname);
1309 if (namelen > 0) {
1310 u8_t len;
1311 const char *p = netif->hostname;
1312 /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME
1313 and 1 byte for trailer) */
1314 size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3;
1315 LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available);
1317 dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, len);
1318 while (len--) {
1319 dhcp_option_byte(dhcp, *p++);
1320 }
1321 }
1322 }
1323}
1324#endif /* LWIP_NETIF_HOSTNAME */
1325
1336static err_t
1337dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p)
1338{
1339 u8_t *options;
1340 u16_t offset;
1341 u16_t offset_max;
1342 u16_t options_idx;
1343 u16_t options_idx_max;
1344 struct pbuf *q;
1345 int parse_file_as_options = 0;
1346 int parse_sname_as_options = 0;
1347
1348 /* clear received options */
1349 dhcp_clear_all_options(dhcp);
1350 /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */
1351 if (p->len < DHCP_SNAME_OFS) {
1352 return ERR_BUF;
1353 }
1354 dhcp->msg_in = (struct dhcp_msg *)p->payload;
1355#if LWIP_DHCP_BOOTP_FILE
1356 /* clear boot file name */
1357 dhcp->boot_file_name[0] = 0;
1358#endif /* LWIP_DHCP_BOOTP_FILE */
1359
1360 /* parse options */
1361
1362 /* start with options field */
1363 options_idx = DHCP_OPTIONS_OFS;
1364 /* parse options to the end of the received packet */
1365 options_idx_max = p->tot_len;
1366again:
1367 q = p;
1368 while((q != NULL) && (options_idx >= q->len)) {
1369 options_idx -= q->len;
1370 options_idx_max -= q->len;
1371 q = q->next;
1372 }
1373 if (q == NULL) {
1374 return ERR_BUF;
1375 }
1376 offset = options_idx;
1377 offset_max = options_idx_max;
1378 options = (u8_t*)q->payload;
1379 /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
1380 while ((q != NULL) && (offset < offset_max) && (options[offset] != DHCP_OPTION_END)) {
1381 u8_t op = options[offset];
1382 u8_t len;
1383 u8_t decode_len = 0;
1384 int decode_idx = -1;
1385 u16_t val_offset = offset + 2;
1386 /* len byte might be in the next pbuf */
1387 if (offset + 1 < q->len) {
1388 len = options[offset + 1];
1389 } else {
1390 len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0);
1391 }
1392 /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
1393 decode_len = len;
1394 switch(op) {
1395 /* case(DHCP_OPTION_END): handled above */
1396 case(DHCP_OPTION_PAD):
1397 /* special option: no len encoded */
1398 decode_len = len = 0;
1399 /* will be increased below */
1400 offset--;
1401 break;
1402 case(DHCP_OPTION_SUBNET_MASK):
1403 LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
1404 decode_idx = DHCP_OPTION_IDX_SUBNET_MASK;
1405 break;
1406 case(DHCP_OPTION_ROUTER):
1407 decode_len = 4; /* only copy the first given router */
1408 LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
1409 decode_idx = DHCP_OPTION_IDX_ROUTER;
1410 break;
1411 case(DHCP_OPTION_DNS_SERVER):
1412 /* special case: there might be more than one server */
1413 LWIP_ERROR("len % 4 == 0", len % 4 == 0, return ERR_VAL;);
1414 /* limit number of DNS servers */
1415 decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS);
1416 LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
1417 decode_idx = DHCP_OPTION_IDX_DNS_SERVER;
1418 break;
1419 case(DHCP_OPTION_LEASE_TIME):
1420 LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
1421 decode_idx = DHCP_OPTION_IDX_LEASE_TIME;
1422 break;
1423 case(DHCP_OPTION_OVERLOAD):
1424 LWIP_ERROR("len == 1", len == 1, return ERR_VAL;);
1425 decode_idx = DHCP_OPTION_IDX_OVERLOAD;
1426 break;
1427 case(DHCP_OPTION_MESSAGE_TYPE):
1428 LWIP_ERROR("len == 1", len == 1, return ERR_VAL;);
1429 decode_idx = DHCP_OPTION_IDX_MSG_TYPE;
1430 break;
1431 case(DHCP_OPTION_SERVER_ID):
1432 LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
1433 decode_idx = DHCP_OPTION_IDX_SERVER_ID;
1434 break;
1435 case(DHCP_OPTION_T1):
1436 LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
1437 decode_idx = DHCP_OPTION_IDX_T1;
1438 break;
1439 case(DHCP_OPTION_T2):
1440 LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
1441 decode_idx = DHCP_OPTION_IDX_T2;
1442 break;
1443 default:
1444 decode_len = 0;
1445 LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", op));
1446 break;
1447 }
1448 offset += len + 2;
1449 if (decode_len > 0) {
1450 u32_t value = 0;
1451 u16_t copy_len;
1452decode_next:
1453 LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX);
1454 if (!dhcp_option_given(dhcp, decode_idx)) {
1455 copy_len = LWIP_MIN(decode_len, 4);
1456 pbuf_copy_partial(q, &value, copy_len, val_offset);
1457 if (decode_len > 4) {
1458 /* decode more than one u32_t */
1459 LWIP_ERROR("decode_len % 4 == 0", decode_len % 4 == 0, return ERR_VAL;);
1460 dhcp_got_option(dhcp, decode_idx);
1461 dhcp_set_option_value(dhcp, decode_idx, htonl(value));
1462 decode_len -= 4;
1463 val_offset += 4;
1464 decode_idx++;
1465 goto decode_next;
1466 } else if (decode_len == 4) {
1467 value = ntohl(value);
1468 } else {
1469 LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;);
1470 value = ((u8_t*)&value)[0];
1471 }
1472 dhcp_got_option(dhcp, decode_idx);
1473 dhcp_set_option_value(dhcp, decode_idx, value);
1474 }
1475 }
1476 if (offset >= q->len) {
1477 offset -= q->len;
1478 offset_max -= q->len;
1479 if ((offset < offset_max) && offset_max) {
1480 q = q->next;
1481 LWIP_ASSERT("next pbuf was null", q);
1482 options = (u8_t*)q->payload;
1483 } else {
1484 // We've run out of bytes, probably no end marker. Don't proceed.
1485 break;
1486 }
1487 }
1488 }
1489 /* is this an overloaded message? */
1490 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) {
1491 u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD);
1492 dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD);
1493 if (overload == DHCP_OVERLOAD_FILE) {
1494 parse_file_as_options = 1;
1495 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n"));
1496 } else if (overload == DHCP_OVERLOAD_SNAME) {
1497 parse_sname_as_options = 1;
1498 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n"));
1499 } else if (overload == DHCP_OVERLOAD_SNAME_FILE) {
1500 parse_sname_as_options = 1;
1501 parse_file_as_options = 1;
1502 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n"));
1503 } else {
1504 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload));
1505 }
1506#if LWIP_DHCP_BOOTP_FILE
1507 if (!parse_file_as_options) {
1508 /* only do this for ACK messages */
1509 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) &&
1510 (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK))
1511 /* copy bootp file name, don't care for sname (server hostname) */
1512 pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS);
1513 /* make sure the string is really NULL-terminated */
1514 dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0;
1515 }
1516#endif /* LWIP_DHCP_BOOTP_FILE */
1517 }
1518 if (parse_file_as_options) {
1519 /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */
1520 parse_file_as_options = 0;
1521 options_idx = DHCP_FILE_OFS;
1522 options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN;
1523 goto again;
1524 } else if (parse_sname_as_options) {
1525 parse_sname_as_options = 0;
1526 options_idx = DHCP_SNAME_OFS;
1527 options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN;
1528 goto again;
1529 }
1530 return ERR_OK;
1531}
1532
1536static void
1537dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
1538{
1539 struct netif *netif = (struct netif *)arg;
1540 struct dhcp *dhcp = netif->dhcp;
1541 struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload;
1542 u8_t msg_type;
1543 u8_t i;
1544 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p,
1546 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
1547 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len));
1548 /* prevent warnings about unused arguments */
1549 LWIP_UNUSED_ARG(pcb);
1552
1553 LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL);
1554
1555 if (p->len < DHCP_MIN_REPLY_LEN) {
1556 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n"));
1557 goto free_pbuf_and_return;
1558 }
1559
1560 if (reply_msg->op != DHCP_BOOTREPLY) {
1561 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op));
1562 goto free_pbuf_and_return;
1563 }
1564 /* iterate through hardware address and match against DHCP message */
1565 for (i = 0; i < netif->hwaddr_len; i++) {
1566 if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
1568 ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
1569 (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i]));
1570 goto free_pbuf_and_return;
1571 }
1572 }
1573 /* match transaction ID against what we expected */
1574 if (ntohl(reply_msg->xid) != dhcp->xid) {
1576 ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid));
1577 goto free_pbuf_and_return;
1578 }
1579 /* option fields could be unfold? */
1580 if (dhcp_parse_reply(dhcp, p) != ERR_OK) {
1582 ("problem unfolding DHCP message - too short on memory?\n"));
1583 goto free_pbuf_and_return;
1584 }
1585
1586 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n"));
1587 /* obtain pointer to DHCP message type */
1588 if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) {
1589 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
1590 goto free_pbuf_and_return;
1591 }
1592
1593 /* read DHCP message type */
1594 msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE);
1595 /* message type is DHCP ACK? */
1596 if (msg_type == DHCP_ACK) {
1597 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n"));
1598 /* in requesting state? */
1599 if (dhcp->state == DHCP_REQUESTING) {
1600 dhcp_handle_ack(netif);
1601#if DHCP_DOES_ARP_CHECK
1602 /* check if the acknowledged lease address is already in use */
1603 dhcp_check(netif);
1604#else
1605 /* bind interface to the acknowledged lease address */
1606 dhcp_bind(netif);
1607#endif
1608 }
1609 /* already bound to the given lease address? */
1610 else if ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING)) {
1611 dhcp_bind(netif);
1612 }
1613 }
1614 /* received a DHCP_NAK in appropriate state? */
1615 else if ((msg_type == DHCP_NAK) &&
1616 ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) ||
1617 (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING ))) {
1618 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n"));
1619 dhcp_handle_nak(netif);
1620 }
1621 /* received a DHCP_OFFER in DHCP_SELECTING state? */
1622 else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) {
1623 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_SELECTING state\n"));
1624 dhcp->request_timeout = 0;
1625 /* remember offered lease */
1626 dhcp_handle_offer(netif);
1627 }
1628free_pbuf_and_return:
1629 dhcp->msg_in = NULL;
1630 pbuf_free(p);
1631}
1632
1640static err_t
1641dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type)
1642{
1643 u16_t i;
1644#ifndef DHCP_GLOBAL_XID
1649#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND)
1650 static u32_t xid;
1651#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
1652 static u32_t xid = 0xABCD0000;
1653#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
1654#else
1655 if (!xid_initialised) {
1656 xid = DHCP_GLOBAL_XID;
1657 xid_initialised = !xid_initialised;
1658 }
1659#endif
1660 LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG;);
1661 LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL;);
1662 LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL);
1663 LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL);
1664 dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
1665 if (dhcp->p_out == NULL) {
1667 ("dhcp_create_msg(): could not allocate pbuf\n"));
1668 return ERR_MEM;
1669 }
1670 LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg",
1671 (dhcp->p_out->len >= sizeof(struct dhcp_msg)));
1672
1673 /* reuse transaction identifier in retransmissions */
1674 if (dhcp->tries == 0) {
1675#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND)
1676 xid = LWIP_RAND();
1677#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
1678 xid++;
1679#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
1680 }
1681 dhcp->xid = xid;
1683 ("transaction id xid(%"X32_F")\n", xid));
1684
1685 dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload;
1686
1687 dhcp->msg_out->op = DHCP_BOOTREQUEST;
1688 /* TODO: make link layer independent */
1689 dhcp->msg_out->htype = DHCP_HTYPE_ETH;
1690 dhcp->msg_out->hlen = netif->hwaddr_len;
1691 dhcp->msg_out->hops = 0;
1692 dhcp->msg_out->xid = htonl(dhcp->xid);
1693 dhcp->msg_out->secs = 0;
1694 /* we don't need the broadcast flag since we can receive unicast traffic
1695 before being fully configured! */
1696 dhcp->msg_out->flags = 0;
1697 ip_addr_set_zero(&dhcp->msg_out->ciaddr);
1698 /* set ciaddr to netif->ip_addr based on message_type and state */
1699 if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) ||
1700 ((message_type == DHCP_REQUEST) && /* DHCP_BOUND not used for sending! */
1701 ((dhcp->state==DHCP_RENEWING) || dhcp->state==DHCP_REBINDING))) {
1702 ip_addr_copy(dhcp->msg_out->ciaddr, netif->ip_addr);
1703 }
1704 ip_addr_set_zero(&dhcp->msg_out->yiaddr);
1705 ip_addr_set_zero(&dhcp->msg_out->siaddr);
1706 ip_addr_set_zero(&dhcp->msg_out->giaddr);
1707 for (i = 0; i < DHCP_CHADDR_LEN; i++) {
1708 /* copy netif hardware address, pad with zeroes */
1709 dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0/* pad byte*/;
1710 }
1711 for (i = 0; i < DHCP_SNAME_LEN; i++) {
1712 dhcp->msg_out->sname[i] = 0;
1713 }
1714 for (i = 0; i < DHCP_FILE_LEN; i++) {
1715 dhcp->msg_out->file[i] = 0;
1716 }
1717 dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
1718 dhcp->options_out_len = 0;
1719 /* fill options field with an incrementing array (for debugging purposes) */
1720 for (i = 0; i < DHCP_OPTIONS_LEN; i++) {
1721 dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */
1722 }
1723 /* Add option MESSAGE_TYPE */
1724 dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
1725 dhcp_option_byte(dhcp, message_type);
1726 return ERR_OK;
1727}
1728
1734static void
1735dhcp_delete_msg(struct dhcp *dhcp)
1736{
1737 LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return;);
1738 LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL);
1739 LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL);
1740 if (dhcp->p_out != NULL) {
1741 pbuf_free(dhcp->p_out);
1742 }
1743 dhcp->p_out = NULL;
1744 dhcp->msg_out = NULL;
1745}
1746
1755static void
1756dhcp_option_trailer(struct dhcp *dhcp)
1757{
1758 LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;);
1759 LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL);
1760 LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
1761 dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
1762 /* packet is too small, or not 4 byte aligned? */
1763 while (((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) &&
1764 (dhcp->options_out_len < DHCP_OPTIONS_LEN)) {
1765 /* add a fill/padding byte */
1766 dhcp->msg_out->options[dhcp->options_out_len++] = 0;
1767 }
1768}
1769
1770#endif /* LWIP_DHCP */
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:73
#define DHCP_SNAME_LEN
Definition: dhcp.h:46
#define DHCP_FILE_LEN
Definition: dhcp.h:47
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
#define LWIP_MIN(x, y)
Definition: def.h:44
#define PP_HTONL(x)
Definition: def.h:90
void dhcp(struct packet *packet)
Definition: dhclient.c:674
#define mem_free(ptr, bsize)
Definition: types.h:124
#define NULL
Definition: types.h:112
UINT op
Definition: effect.c:236
static WCHAR available[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2336
USHORT port
Definition: uri.c:228
#define X16_F
Definition: cc.h:38
signed short s16_t
Definition: cc.h:29
#define U16_F
Definition: cc.h:36
#define X32_F
Definition: cc.h:41
unsigned long u32_t
Definition: cc.h:25
#define U32_F
Definition: cc.h:39
unsigned char u8_t
Definition: cc.h:23
unsigned short u16_t
Definition: cc.h:24
void * mem_malloc(mem_size_t size)
Definition: mem.c:494
#define ip_set_option(pcb, opt)
Definition: ip.h:207
#define SOF_BROADCAST
Definition: ip.h:102
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:47
#define LWIP_DBG_STATE
Definition: debug.h:59
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:95
#define LWIP_DBG_LEVEL_WARNING
Definition: debug.h:46
#define LWIP_ERROR(message, expression, handler)
Definition: debug.h:74
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:66
#define LWIP_DBG_TRACE
Definition: debug.h:57
#define ERR_MEM
Definition: err.h:53
#define ERR_ARG
Definition: err.h:70
#define ERR_OK
Definition: err.h:52
#define ERR_VAL
Definition: err.h:58
#define ERR_BUF
Definition: err.h:54
s8_t err_t
Definition: err.h:47
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLdouble n
Definition: glext.h:7729
GLint namelen
Definition: glext.h:7232
GLenum const GLvoid * addr
Definition: glext.h:9621
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ip_addr_cmp(addr1, addr2)
Definition: ip_addr.h:198
#define ip_addr_isany(addr1)
Definition: ip_addr.h:200
#define ip4_addr1_16(ipaddr)
Definition: ip_addr.h:226
#define ip4_addr1(ipaddr)
Definition: ip_addr.h:220
#define ip4_addr2_16(ipaddr)
Definition: ip_addr.h:227
#define IP_ADDR_ANY
Definition: ip_addr.h:92
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:162
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
Definition: ip_addr.h:64
#define ip_addr_set_any(ipaddr)
Definition: ip_addr.h:170
#define ip4_addr3_16(ipaddr)
Definition: ip_addr.h:228
#define ip_addr_set_zero(ipaddr)
Definition: ip_addr.h:168
#define ip_addr_get_network(target, host, netmask)
Definition: ip_addr.h:184
#define ip4_addr4_16(ipaddr)
Definition: ip_addr.h:229
#define ip4_addr_get_u32(src_ipaddr)
Definition: ip_addr.h:181
#define IP_ADDR_BROADCAST
Definition: ip_addr.h:93
#define ip4_addr_set_u32(dest_ipaddr, src_u32)
Definition: ip_addr.h:179
#define ntohl(x)
Definition: module.h:205
#define htonl(x)
Definition: module.h:214
void netif_set_netmask(struct netif *netif, ip_addr_t *netmask)
Definition: netif.c:409
struct netif * netif_list
Definition: netif.c:75
void netif_set_down(struct netif *netif)
Definition: netif.c:490
void netif_set_gw(struct netif *netif, ip_addr_t *gw)
Definition: netif.c:388
void netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr)
Definition: netif.c:323
void netif_set_up(struct netif *netif)
Definition: netif.c:453
#define NETIF_FLAG_ETHARP
Definition: netif.h:88
#define NETIF_FLAG_DHCP
Definition: netif.h:78
LONGLONG xid
Definition: nfs41_driver.c:106
#define LWIP_DHCP_AUTOIP_COOP_TRIES
Definition: opt.h:720
#define DHCP_DEBUG
Definition: opt.h:2102
#define DNS_MAX_SERVERS
Definition: opt.h:833
void pbuf_realloc(struct pbuf *p, u16_t new_len)
Definition: pbuf.c:430
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:207
u16_t pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:918
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:618
@ PBUF_RAM
Definition: pbuf.h:58
@ PBUF_TRANSPORT
Definition: pbuf.h:51
msg_type
Definition: rpc_msg.h:77
#define memset(x, y, z)
Definition: compat.h:39
Definition: netif.h:136
u8_t flags
Definition: netif.h:192
char name[2]
Definition: netif.h:194
void * state
Definition: netif.h:172
ip_addr_t ip_addr
Definition: netif.h:141
u8_t num
Definition: netif.h:196
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Definition: netif.h:190
u16_t mtu
Definition: netif.h:186
struct netif * next
Definition: netif.h:138
u8_t hwaddr_len
Definition: netif.h:188
Definition: pbuf.h:79
Definition: dhcpd.h:245
Definition: pdh_main.c:94