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