ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dhcp.c
Go to the documentation of this file.
00001 
00007 /*
00008  *
00009  * Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@gmx.net>
00010  * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
00011  * All rights reserved.
00012  *
00013  * Redistribution and use in source and binary forms, with or without modification,
00014  * are permitted provided that the following conditions are met:
00015  *
00016  * 1. Redistributions of source code must retain the above copyright notice,
00017  *    this list of conditions and the following disclaimer.
00018  * 2. Redistributions in binary form must reproduce the above copyright notice,
00019  *    this list of conditions and the following disclaimer in the documentation
00020  *    and/or other materials provided with the distribution.
00021  * 3. The name of the author may not be used to endorse or promote products
00022  *    derived from this software without specific prior written permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00025  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00026  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00027  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00028  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00029  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00032  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00033  * OF SUCH DAMAGE.
00034  *
00035  * This file is a contribution to the lwIP TCP/IP stack.
00036  * The Swedish Institute of Computer Science and Adam Dunkels
00037  * are specifically granted permission to redistribute this
00038  * source code.
00039  *
00040  * Author: Leon Woestenberg <leon.woestenberg@gmx.net>
00041  *
00042  * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform
00043  * with RFC 2131 and RFC 2132.
00044  *
00045  * TODO:
00046  * - Support for interfaces other than Ethernet (SLIP, PPP, ...)
00047  *
00048  * Please coordinate changes and requests with Leon Woestenberg
00049  * <leon.woestenberg@gmx.net>
00050  *
00051  * Integration with your code:
00052  *
00053  * In lwip/dhcp.h
00054  * #define DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute)
00055  * #define DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer)
00056  *
00057  * Then have your application call dhcp_coarse_tmr() and
00058  * dhcp_fine_tmr() on the defined intervals.
00059  *
00060  * dhcp_start(struct netif *netif);
00061  * starts a DHCP client instance which configures the interface by
00062  * obtaining an IP address lease and maintaining it.
00063  *
00064  * Use dhcp_release(netif) to end the lease and use dhcp_stop(netif)
00065  * to remove the DHCP client.
00066  *
00067  */
00068 
00069 #include "lwip/opt.h"
00070 
00071 #if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */
00072 
00073 #include "lwip/stats.h"
00074 #include "lwip/mem.h"
00075 #include "lwip/udp.h"
00076 #include "lwip/ip_addr.h"
00077 #include "lwip/netif.h"
00078 #include "lwip/def.h"
00079 #include "lwip/sys.h"
00080 #include "lwip/dhcp.h"
00081 #include "lwip/autoip.h"
00082 #include "lwip/dns.h"
00083 #include "netif/etharp.h"
00084 
00085 #include <string.h>
00086 
00092 #ifdef DHCP_GLOBAL_XID_HEADER
00093 #include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */
00094 #endif
00095 
00098 #define DHCP_MAX_MSG_LEN(netif)        (netif->mtu)
00099 #define DHCP_MAX_MSG_LEN_MIN_REQUIRED  576
00100 
00101 #define DHCP_MIN_REPLY_LEN             44
00102 
00103 #define REBOOT_TRIES 2
00104 
00110 #define DHCP_OPTION_IDX_OVERLOAD    0
00111 #define DHCP_OPTION_IDX_MSG_TYPE    1
00112 #define DHCP_OPTION_IDX_SERVER_ID   2
00113 #define DHCP_OPTION_IDX_LEASE_TIME  3
00114 #define DHCP_OPTION_IDX_T1          4
00115 #define DHCP_OPTION_IDX_T2          5
00116 #define DHCP_OPTION_IDX_SUBNET_MASK 6
00117 #define DHCP_OPTION_IDX_ROUTER      7
00118 #define DHCP_OPTION_IDX_DNS_SERVER  8
00119 #define DHCP_OPTION_IDX_MAX         (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS)
00120 
00123 u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX];
00127 u8_t  dhcp_rx_options_given[DHCP_OPTION_IDX_MAX];
00128 
00129 #define dhcp_option_given(dhcp, idx)          (dhcp_rx_options_given[idx] != 0)
00130 #define dhcp_got_option(dhcp, idx)            (dhcp_rx_options_given[idx] = 1)
00131 #define dhcp_clear_option(dhcp, idx)          (dhcp_rx_options_given[idx] = 0)
00132 #define dhcp_clear_all_options(dhcp)          (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given)))
00133 #define dhcp_get_option_value(dhcp, idx)      (dhcp_rx_options_val[idx])
00134 #define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val))
00135 
00136 
00137 /* DHCP client state machine functions */
00138 static err_t dhcp_discover(struct netif *netif);
00139 static err_t dhcp_select(struct netif *netif);
00140 static void dhcp_bind(struct netif *netif);
00141 #if DHCP_DOES_ARP_CHECK
00142 static err_t dhcp_decline(struct netif *netif);
00143 #endif /* DHCP_DOES_ARP_CHECK */
00144 static err_t dhcp_rebind(struct netif *netif);
00145 static err_t dhcp_reboot(struct netif *netif);
00146 static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
00147 
00148 /* receive, unfold, parse and free incoming messages */
00149 static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
00150 
00151 /* set the DHCP timers */
00152 static void dhcp_timeout(struct netif *netif);
00153 static void dhcp_t1_timeout(struct netif *netif);
00154 static void dhcp_t2_timeout(struct netif *netif);
00155 
00156 /* build outgoing messages */
00157 /* create a DHCP message, fill in common headers */
00158 static err_t dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type);
00159 /* free a DHCP request */
00160 static void dhcp_delete_msg(struct dhcp *dhcp);
00161 /* add a DHCP option (type, then length in bytes) */
00162 static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len);
00163 /* add option values */
00164 static void dhcp_option_byte(struct dhcp *dhcp, u8_t value);
00165 static void dhcp_option_short(struct dhcp *dhcp, u16_t value);
00166 static void dhcp_option_long(struct dhcp *dhcp, u32_t value);
00167 /* always add the DHCP options trailer to end and pad */
00168 static void dhcp_option_trailer(struct dhcp *dhcp);
00169 
00182 static void
00183 dhcp_handle_nak(struct netif *netif)
00184 {
00185   struct dhcp *dhcp = netif->dhcp;
00186   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n", 
00187     (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
00188   /* Set the interface down since the address must no longer be used, as per RFC2131 */
00189   netif_set_down(netif);
00190   /* remove IP address from interface */
00191   netif_set_ipaddr(netif, IP_ADDR_ANY);
00192   netif_set_gw(netif, IP_ADDR_ANY);
00193   netif_set_netmask(netif, IP_ADDR_ANY); 
00194   /* Change to a defined state */
00195   dhcp_set_state(dhcp, DHCP_BACKING_OFF);
00196   /* We can immediately restart discovery */
00197   dhcp_discover(netif);
00198 }
00199 
00200 #if DHCP_DOES_ARP_CHECK
00201 
00210 static void
00211 dhcp_check(struct netif *netif)
00212 {
00213   struct dhcp *dhcp = netif->dhcp;
00214   err_t result;
00215   u16_t msecs;
00216   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
00217     (s16_t)netif->name[1]));
00218   dhcp_set_state(dhcp, DHCP_CHECKING);
00219   /* create an ARP query for the offered IP address, expecting that no host
00220      responds, as the IP address should not be in use. */
00221   result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
00222   if (result != ERR_OK) {
00223     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n"));
00224   }
00225   dhcp->tries++;
00226   msecs = 500;
00227   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00228   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs));
00229 }
00230 #endif /* DHCP_DOES_ARP_CHECK */
00231 
00237 static void
00238 dhcp_handle_offer(struct netif *netif)
00239 {
00240   struct dhcp *dhcp = netif->dhcp;
00241   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
00242     (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
00243   /* obtain the server address */
00244   if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) {
00245     ip4_addr_set_u32(&dhcp->server_ip_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID)));
00246     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n",
00247       ip4_addr_get_u32(&dhcp->server_ip_addr)));
00248     /* remember offered address */
00249     ip_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr);
00250     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n",
00251       ip4_addr_get_u32(&dhcp->offered_ip_addr)));
00252 
00253     dhcp_select(netif);
00254   } else {
00255     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
00256       ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void*)netif));
00257   }
00258 }
00259 
00268 static err_t
00269 dhcp_select(struct netif *netif)
00270 {
00271   struct dhcp *dhcp = netif->dhcp;
00272   err_t result;
00273   u16_t msecs;
00274 
00275   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));
00276   dhcp_set_state(dhcp, DHCP_REQUESTING);
00277 
00278   /* create and initialize the DHCP message header */
00279   result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
00280   if (result == ERR_OK) {
00281     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00282     dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
00283 
00284     /* MUST request the offered IP address */
00285     dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
00286     dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
00287 
00288     dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
00289     dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->server_ip_addr)));
00290 
00291     dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
00292     dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
00293     dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
00294     dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
00295     dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
00296 
00297 #if LWIP_NETIF_HOSTNAME
00298     if (netif->hostname != NULL) {
00299       const char *p = (const char*)netif->hostname;
00300       u8_t namelen = (u8_t)strlen(p);
00301       if (namelen > 0) {
00302         LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255);
00303         dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen);
00304         while (*p) {
00305           dhcp_option_byte(dhcp, *p++);
00306         }
00307       }
00308     }
00309 #endif /* LWIP_NETIF_HOSTNAME */
00310 
00311     dhcp_option_trailer(dhcp);
00312     /* shrink the pbuf to the actual content length */
00313     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00314 
00315     /* send broadcast to any DHCP server */
00316     udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
00317     dhcp_delete_msg(dhcp);
00318     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n"));
00319   } else {
00320     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n"));
00321   }
00322   dhcp->tries++;
00323   msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
00324   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00325   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs));
00326   return result;
00327 }
00328 
00332 void
00333 dhcp_coarse_tmr()
00334 {
00335   struct netif *netif = netif_list;
00336   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n"));
00337   /* iterate through all network interfaces */
00338   while (netif != NULL) {
00339     /* only act on DHCP configured interfaces */
00340     if (netif->dhcp != NULL) {
00341       /* timer is active (non zero), and triggers (zeroes) now? */
00342       if (netif->dhcp->t2_timeout-- == 1) {
00343         LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n"));
00344         /* this clients' rebind timeout triggered */
00345         dhcp_t2_timeout(netif);
00346       /* timer is active (non zero), and triggers (zeroes) now */
00347       } else if (netif->dhcp->t1_timeout-- == 1) {
00348         LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n"));
00349         /* this clients' renewal timeout triggered */
00350         dhcp_t1_timeout(netif);
00351       }
00352     }
00353     /* proceed to next netif */
00354     netif = netif->next;
00355   }
00356 }
00357 
00364 void
00365 dhcp_fine_tmr()
00366 {
00367   struct netif *netif = netif_list;
00368   /* loop through netif's */
00369   while (netif != NULL) {
00370     /* only act on DHCP configured interfaces */
00371     if (netif->dhcp != NULL) {
00372       /* timer is active (non zero), and is about to trigger now */      
00373       if (netif->dhcp->request_timeout > 1) {
00374         netif->dhcp->request_timeout--;
00375       }
00376       else if (netif->dhcp->request_timeout == 1) {
00377         netif->dhcp->request_timeout--;
00378         /* { netif->dhcp->request_timeout == 0 } */
00379         LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
00380         /* this client's request timeout triggered */
00381         dhcp_timeout(netif);
00382       }
00383     }
00384     /* proceed to next network interface */
00385     netif = netif->next;
00386   }
00387 }
00388 
00397 static void
00398 dhcp_timeout(struct netif *netif)
00399 {
00400   struct dhcp *dhcp = netif->dhcp;
00401   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n"));
00402   /* back-off period has passed, or server selection timed out */
00403   if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) {
00404     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n"));
00405     dhcp_discover(netif);
00406   /* receiving the requested lease timed out */
00407   } else if (dhcp->state == DHCP_REQUESTING) {
00408     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n"));
00409     if (dhcp->tries <= 5) {
00410       dhcp_select(netif);
00411     } else {
00412       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n"));
00413       dhcp_release(netif);
00414       dhcp_discover(netif);
00415     }
00416 #if DHCP_DOES_ARP_CHECK
00417   /* received no ARP reply for the offered address (which is good) */
00418   } else if (dhcp->state == DHCP_CHECKING) {
00419     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n"));
00420     if (dhcp->tries <= 1) {
00421       dhcp_check(netif);
00422     /* no ARP replies on the offered address,
00423        looks like the IP address is indeed free */
00424     } else {
00425       /* bind the interface to the offered address */
00426       dhcp_bind(netif);
00427     }
00428 #endif /* DHCP_DOES_ARP_CHECK */
00429   }
00430   /* did not get response to renew request? */
00431   else if (dhcp->state == DHCP_RENEWING) {
00432     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RENEWING, DHCP request timed out\n"));
00433     /* just retry renewal */
00434     /* note that the rebind timer will eventually time-out if renew does not work */
00435     dhcp_renew(netif);
00436   /* did not get response to rebind request? */
00437   } else if (dhcp->state == DHCP_REBINDING) {
00438     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REBINDING, DHCP request timed out\n"));
00439     if (dhcp->tries <= 8) {
00440       dhcp_rebind(netif);
00441     } else {
00442       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RELEASING, DISCOVERING\n"));
00443       dhcp_release(netif);
00444       dhcp_discover(netif);
00445     }
00446   } else if (dhcp->state == DHCP_REBOOTING) {
00447     if (dhcp->tries < REBOOT_TRIES) {
00448       dhcp_reboot(netif);
00449     } else {
00450       dhcp_discover(netif);
00451     }
00452   }
00453 }
00454 
00460 static void
00461 dhcp_t1_timeout(struct netif *netif)
00462 {
00463   struct dhcp *dhcp = netif->dhcp;
00464   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n"));
00465   if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) ||
00466       (dhcp->state == DHCP_RENEWING)) {
00467     /* just retry to renew - note that the rebind timer (t2) will
00468      * eventually time-out if renew tries fail. */
00469     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00470                 ("dhcp_t1_timeout(): must renew\n"));
00471     /* This slightly different to RFC2131: DHCPREQUEST will be sent from state
00472        DHCP_RENEWING, not DHCP_BOUND */
00473     dhcp_renew(netif);
00474   }
00475 }
00476 
00482 static void
00483 dhcp_t2_timeout(struct netif *netif)
00484 {
00485   struct dhcp *dhcp = netif->dhcp;
00486   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n"));
00487   if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) ||
00488       (dhcp->state == DHCP_RENEWING)) {
00489     /* just retry to rebind */
00490     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00491                 ("dhcp_t2_timeout(): must rebind\n"));
00492     /* This slightly different to RFC2131: DHCPREQUEST will be sent from state
00493        DHCP_REBINDING, not DHCP_BOUND */
00494     dhcp_rebind(netif);
00495   }
00496 }
00497 
00503 static void
00504 dhcp_handle_ack(struct netif *netif)
00505 {
00506   struct dhcp *dhcp = netif->dhcp;
00507 #if LWIP_DNS
00508   u8_t n;
00509 #endif /* LWIP_DNS */
00510 
00511   /* clear options we might not get from the ACK */
00512   ip_addr_set_zero(&dhcp->offered_sn_mask);
00513   ip_addr_set_zero(&dhcp->offered_gw_addr);
00514 #if LWIP_DHCP_BOOTP_FILE
00515   ip_addr_set_zero(&dhcp->offered_si_addr);
00516 #endif /* LWIP_DHCP_BOOTP_FILE */
00517 
00518   /* lease time given? */
00519   if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) {
00520     /* remember offered lease time */
00521     dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME);
00522   }
00523   /* renewal period given? */
00524   if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) {
00525     /* remember given renewal period */
00526     dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1);
00527   } else {
00528     /* calculate safe periods for renewal */
00529     dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2;
00530   }
00531 
00532   /* renewal period given? */
00533   if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) {
00534     /* remember given rebind period */
00535     dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2);
00536   } else {
00537     /* calculate safe periods for rebinding */
00538     dhcp->offered_t2_rebind = dhcp->offered_t0_lease;
00539   }
00540 
00541   /* (y)our internet address */
00542   ip_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr);
00543 
00544 #if LWIP_DHCP_BOOTP_FILE
00545   /* copy boot server address,
00546      boot file name copied in dhcp_parse_reply if not overloaded */
00547   ip_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr);
00548 #endif /* LWIP_DHCP_BOOTP_FILE */
00549 
00550   /* subnet mask given? */
00551   if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) {
00552     /* remember given subnet mask */
00553     ip4_addr_set_u32(&dhcp->offered_sn_mask, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)));
00554     dhcp->subnet_mask_given = 1;
00555   } else {
00556     dhcp->subnet_mask_given = 0;
00557   }
00558 
00559   /* gateway router */
00560   if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) {
00561     ip4_addr_set_u32(&dhcp->offered_gw_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER)));
00562   }
00563   
00564 #if LWIP_DNS
00565   /* DNS servers */
00566   n = 0;
00567   while(dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n) && (n < DNS_MAX_SERVERS)) {
00568     ip_addr_t dns_addr;
00569     ip4_addr_set_u32(&dns_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
00570     dns_setserver(n, &dns_addr);
00571     n++;
00572   }
00573 #endif /* LWIP_DNS */
00574 }
00575 
00582 void
00583 dhcp_set_struct(struct netif *netif, struct dhcp *dhcp)
00584 {
00585   LWIP_ASSERT("netif != NULL", netif != NULL);
00586   LWIP_ASSERT("dhcp != NULL", dhcp != NULL);
00587   LWIP_ASSERT("netif already has a struct dhcp set", netif->dhcp == NULL);
00588 
00589   /* clear data structure */
00590   memset(dhcp, 0, sizeof(struct dhcp));
00591   /* dhcp_set_state(&dhcp, DHCP_OFF); */
00592   netif->dhcp = dhcp;
00593 }
00594 
00602 void dhcp_cleanup(struct netif *netif)
00603 {
00604   LWIP_ASSERT("netif != NULL", netif != NULL);
00605 
00606   if (netif->dhcp != NULL) {
00607     mem_free(netif->dhcp);
00608     netif->dhcp = NULL;
00609   }
00610 }
00611 
00624 err_t
00625 dhcp_start(struct netif *netif)
00626 {
00627   struct dhcp *dhcp;
00628   err_t result = ERR_OK;
00629 
00630   LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
00631   dhcp = netif->dhcp;
00632   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));
00633   /* Remove the flag that says this netif is handled by DHCP,
00634      it is set when we succeeded starting. */
00635   netif->flags &= ~NETIF_FLAG_DHCP;
00636 
00637   /* check hwtype of the netif */
00638   if ((netif->flags & NETIF_FLAG_ETHARP) == 0) {
00639     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): No ETHARP netif\n"));
00640     return ERR_ARG;
00641   }
00642 
00643   /* check MTU of the netif */
00644   if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) {
00645     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n"));
00646     return ERR_MEM;
00647   }
00648 
00649   /* no DHCP client attached yet? */
00650   if (dhcp == NULL) {
00651     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
00652     dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp));
00653     if (dhcp == NULL) {
00654       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
00655       return ERR_MEM;
00656     }
00657     /* store this dhcp client in the netif */
00658     netif->dhcp = dhcp;
00659     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp"));
00660   /* already has DHCP client attached */
00661   } else {
00662     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n"));
00663     if (dhcp->pcb != NULL) {
00664       udp_remove(dhcp->pcb);
00665     }
00666     LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL);
00667     LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL );
00668   }
00669     
00670   /* clear data structure */
00671   memset(dhcp, 0, sizeof(struct dhcp));
00672   /* dhcp_set_state(&dhcp, DHCP_OFF); */
00673   /* allocate UDP PCB */
00674   dhcp->pcb = udp_new();
00675   if (dhcp->pcb == NULL) {
00676     LWIP_DEBUGF(DHCP_DEBUG  | LWIP_DBG_TRACE, ("dhcp_start(): could not obtain pcb\n"));
00677     return ERR_MEM;
00678   }
00679   dhcp->pcb->so_options |= SOF_BROADCAST;
00680   /* set up local and remote port for the pcb */
00681   udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00682   udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
00683   /* set up the recv callback and argument */
00684   udp_recv(dhcp->pcb, dhcp_recv, netif);
00685   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
00686   /* (re)start the DHCP negotiation */
00687   result = dhcp_discover(netif);
00688   if (result != ERR_OK) {
00689     /* free resources allocated above */
00690     dhcp_stop(netif);
00691     return ERR_MEM;
00692   }
00693   /* Set the flag that says this netif is handled by DHCP. */
00694   netif->flags |= NETIF_FLAG_DHCP;
00695   return result;
00696 }
00697 
00707 void
00708 dhcp_inform(struct netif *netif)
00709 {
00710   struct dhcp dhcp;
00711   err_t result = ERR_OK;
00712   struct udp_pcb *pcb;
00713 
00714   LWIP_ERROR("netif != NULL", (netif != NULL), return;);
00715 
00716   memset(&dhcp, 0, sizeof(struct dhcp));
00717   dhcp_set_state(&dhcp, DHCP_INFORM);
00718 
00719   if ((netif->dhcp != NULL) && (netif->dhcp->pcb != NULL)) {
00720     /* re-use existing pcb */
00721     pcb = netif->dhcp->pcb;
00722   } else {
00723     pcb = udp_new();
00724     if (pcb == NULL) {
00725       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not obtain pcb"));
00726       return;
00727     }
00728     dhcp.pcb = pcb;
00729     dhcp.pcb->so_options |= SOF_BROADCAST;
00730     udp_bind(dhcp.pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
00731     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n"));
00732   }
00733   /* create and initialize the DHCP message header */
00734   result = dhcp_create_msg(netif, &dhcp, DHCP_INFORM);
00735   if (result == ERR_OK) {
00736     dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00737     dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif));
00738 
00739     dhcp_option_trailer(&dhcp);
00740 
00741     pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len);
00742 
00743     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n"));
00744     udp_sendto_if(pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
00745     dhcp_delete_msg(&dhcp);
00746   } else {
00747     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n"));
00748   }
00749 
00750   if (dhcp.pcb != NULL) {
00751     /* otherwise, the existing pcb was used */
00752     udp_remove(dhcp.pcb);
00753   }
00754 }
00755 
00761 void
00762 dhcp_network_changed(struct netif *netif)
00763 {
00764   struct dhcp *dhcp = netif->dhcp;
00765   if (!dhcp)
00766     return;
00767   switch (dhcp->state) {
00768   case DHCP_REBINDING:
00769   case DHCP_RENEWING:
00770   case DHCP_BOUND:
00771   case DHCP_REBOOTING:
00772     netif_set_down(netif);
00773     dhcp->tries = 0;
00774     dhcp_reboot(netif);
00775     break;
00776   case DHCP_OFF:
00777     /* stay off */
00778     break;
00779   default:
00780     dhcp->tries = 0;
00781 #if LWIP_DHCP_AUTOIP_COOP
00782     if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
00783       autoip_stop(netif);
00784       dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
00785     }
00786 #endif /* LWIP_DHCP_AUTOIP_COOP */
00787     dhcp_discover(netif);
00788     break;
00789   }
00790 }
00791 
00792 #if DHCP_DOES_ARP_CHECK
00793 
00799 void dhcp_arp_reply(struct netif *netif, ip_addr_t *addr)
00800 {
00801   LWIP_ERROR("netif != NULL", (netif != NULL), return;);
00802   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n"));
00803   /* is a DHCP client doing an ARP check? */
00804   if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
00805     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n",
00806       ip4_addr_get_u32(addr)));
00807     /* did a host respond with the address we
00808        were offered by the DHCP server? */
00809     if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
00810       /* we will not accept the offered address */
00811       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
00812         ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
00813       dhcp_decline(netif);
00814     }
00815   }
00816 }
00817 
00827 static err_t
00828 dhcp_decline(struct netif *netif)
00829 {
00830   struct dhcp *dhcp = netif->dhcp;
00831   err_t result = ERR_OK;
00832   u16_t msecs;
00833   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n"));
00834   dhcp_set_state(dhcp, DHCP_BACKING_OFF);
00835   /* create and initialize the DHCP message header */
00836   result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE);
00837   if (result == ERR_OK) {
00838     dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
00839     dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
00840 
00841     dhcp_option_trailer(dhcp);
00842     /* resize pbuf to reflect true size of options */
00843     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00844 
00845     /* per section 4.4.4, broadcast DECLINE messages */
00846     udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
00847     dhcp_delete_msg(dhcp);
00848     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
00849   } else {
00850     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
00851       ("dhcp_decline: could not allocate DHCP request\n"));
00852   }
00853   dhcp->tries++;
00854   msecs = 10*1000;
00855   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00856   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs));
00857   return result;
00858 }
00859 #endif /* DHCP_DOES_ARP_CHECK */
00860 
00861 
00867 static err_t
00868 dhcp_discover(struct netif *netif)
00869 {
00870   struct dhcp *dhcp = netif->dhcp;
00871   err_t result = ERR_OK;
00872   u16_t msecs;
00873   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n"));
00874   ip_addr_set_any(&dhcp->offered_ip_addr);
00875   dhcp_set_state(dhcp, DHCP_SELECTING);
00876   /* create and initialize the DHCP message header */
00877   result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER);
00878   if (result == ERR_OK) {
00879     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n"));
00880 
00881     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00882     dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
00883 
00884     dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
00885     dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
00886     dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
00887     dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
00888     dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
00889 
00890     dhcp_option_trailer(dhcp);
00891 
00892     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n"));
00893     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
00894 
00895     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
00896     udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
00897     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
00898     dhcp_delete_msg(dhcp);
00899     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
00900   } else {
00901     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n"));
00902   }
00903   dhcp->tries++;
00904 #if LWIP_DHCP_AUTOIP_COOP
00905   if(dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) {
00906     dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON;
00907     autoip_start(netif);
00908   }
00909 #endif /* LWIP_DHCP_AUTOIP_COOP */
00910   msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
00911   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
00912   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs));
00913   return result;
00914 }
00915 
00916 
00922 static void
00923 dhcp_bind(struct netif *netif)
00924 {
00925   u32_t timeout;
00926   struct dhcp *dhcp;
00927   ip_addr_t sn_mask, gw_addr;
00928   LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;);
00929   dhcp = netif->dhcp;
00930   LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;);
00931   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));
00932 
00933   /* temporary DHCP lease? */
00934   if (dhcp->offered_t1_renew != 0xffffffffUL) {
00935     /* set renewal period timer */
00936     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew));
00937     timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
00938     if(timeout > 0xffff) {
00939       timeout = 0xffff;
00940     }
00941     dhcp->t1_timeout = (u16_t)timeout;
00942     if (dhcp->t1_timeout == 0) {
00943       dhcp->t1_timeout = 1;
00944     }
00945     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000));
00946   }
00947   /* set renewal period timer */
00948   if (dhcp->offered_t2_rebind != 0xffffffffUL) {
00949     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind));
00950     timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
00951     if(timeout > 0xffff) {
00952       timeout = 0xffff;
00953     }
00954     dhcp->t2_timeout = (u16_t)timeout;
00955     if (dhcp->t2_timeout == 0) {
00956       dhcp->t2_timeout = 1;
00957     }
00958     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000));
00959   }
00960 
00961   if (dhcp->subnet_mask_given) {
00962     /* copy offered network mask */
00963     ip_addr_copy(sn_mask, dhcp->offered_sn_mask);
00964   } else {
00965     /* subnet mask not given, choose a safe subnet mask given the network class */
00966     u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr);
00967     if (first_octet <= 127) {
00968       ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL));
00969     } else if (first_octet >= 192) {
00970       ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL));
00971     } else {
00972       ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL));
00973     }
00974   }
00975 
00976   ip_addr_copy(gw_addr, dhcp->offered_gw_addr);
00977   /* gateway address not given? */
00978   if (ip_addr_isany(&gw_addr)) {
00979     /* copy network address */
00980     ip_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask);
00981     /* use first host address on network as gateway */
00982     ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL));
00983   }
00984 
00985 #if LWIP_DHCP_AUTOIP_COOP
00986   if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
00987     autoip_stop(netif);
00988     dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
00989   }
00990 #endif /* LWIP_DHCP_AUTOIP_COOP */
00991 
00992   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n",
00993     ip4_addr_get_u32(&dhcp->offered_ip_addr)));
00994   netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
00995   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n",
00996     ip4_addr_get_u32(&sn_mask)));
00997   netif_set_netmask(netif, &sn_mask);
00998   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n",
00999     ip4_addr_get_u32(&gw_addr)));
01000   netif_set_gw(netif, &gw_addr);
01001   /* bring the interface up */
01002   netif_set_up(netif);
01003   /* netif is now bound to DHCP leased address */
01004   dhcp_set_state(dhcp, DHCP_BOUND);
01005 }
01006 
01012 err_t
01013 dhcp_renew(struct netif *netif)
01014 {
01015   struct dhcp *dhcp = netif->dhcp;
01016   err_t result;
01017   u16_t msecs;
01018   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n"));
01019   dhcp_set_state(dhcp, DHCP_RENEWING);
01020 
01021   /* create and initialize the DHCP message header */
01022   result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
01023   if (result == ERR_OK) {
01024     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
01025     dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
01026 
01027 #if LWIP_NETIF_HOSTNAME
01028     if (netif->hostname != NULL) {
01029       const char *p = (const char*)netif->hostname;
01030       u8_t namelen = (u8_t)strlen(p);
01031       if (namelen > 0) {
01032         LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255);
01033         dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen);
01034         while (*p) {
01035           dhcp_option_byte(dhcp, *p++);
01036         }
01037       }
01038     }
01039 #endif /* LWIP_NETIF_HOSTNAME */
01040 
01041 #if 0
01042     dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
01043     dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
01044 #endif
01045 
01046 #if 0
01047     dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
01048     dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
01049 #endif
01050     /* append DHCP message trailer */
01051     dhcp_option_trailer(dhcp);
01052 
01053     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
01054 
01055     udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
01056     dhcp_delete_msg(dhcp);
01057 
01058     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n"));
01059   } else {
01060     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n"));
01061   }
01062   dhcp->tries++;
01063   /* back-off on retries, but to a maximum of 20 seconds */
01064   msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
01065   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
01066   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs));
01067   return result;
01068 }
01069 
01075 static err_t
01076 dhcp_rebind(struct netif *netif)
01077 {
01078   struct dhcp *dhcp = netif->dhcp;
01079   err_t result;
01080   u16_t msecs;
01081   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n"));
01082   dhcp_set_state(dhcp, DHCP_REBINDING);
01083 
01084   /* create and initialize the DHCP message header */
01085   result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
01086   if (result == ERR_OK) {
01087     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
01088     dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
01089 
01090 #if LWIP_NETIF_HOSTNAME
01091     if (netif->hostname != NULL) {
01092       const char *p = (const char*)netif->hostname;
01093       u8_t namelen = (u8_t)strlen(p);
01094       if (namelen > 0) {
01095         LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255);
01096         dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen);
01097         while (*p) {
01098           dhcp_option_byte(dhcp, *p++);
01099         }
01100       }
01101     }
01102 #endif /* LWIP_NETIF_HOSTNAME */
01103 
01104 #if 0
01105     dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
01106     dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
01107 
01108     dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
01109     dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
01110 #endif
01111 
01112     dhcp_option_trailer(dhcp);
01113 
01114     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
01115 
01116     /* broadcast to server */
01117     udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
01118     dhcp_delete_msg(dhcp);
01119     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n"));
01120   } else {
01121     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n"));
01122   }
01123   dhcp->tries++;
01124   msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
01125   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
01126   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs));
01127   return result;
01128 }
01129 
01135 static err_t
01136 dhcp_reboot(struct netif *netif)
01137 {
01138   struct dhcp *dhcp = netif->dhcp;
01139   err_t result;
01140   u16_t msecs;
01141   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n"));
01142   dhcp_set_state(dhcp, DHCP_REBOOTING);
01143 
01144   /* create and initialize the DHCP message header */
01145   result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
01146   if (result == ERR_OK) {
01147     dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
01148     dhcp_option_short(dhcp, 576);
01149 
01150     dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
01151     dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
01152 
01153     dhcp_option_trailer(dhcp);
01154 
01155     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
01156 
01157     /* broadcast to server */
01158     udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
01159     dhcp_delete_msg(dhcp);
01160     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n"));
01161   } else {
01162     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n"));
01163   }
01164   dhcp->tries++;
01165   msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
01166   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
01167   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs));
01168   return result;
01169 }
01170 
01171 
01177 err_t
01178 dhcp_release(struct netif *netif)
01179 {
01180   struct dhcp *dhcp = netif->dhcp;
01181   err_t result;
01182   u16_t msecs;
01183   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n"));
01184 
01185   /* idle DHCP client */
01186   dhcp_set_state(dhcp, DHCP_OFF);
01187   /* clean old DHCP offer */
01188   ip_addr_set_zero(&dhcp->server_ip_addr);
01189   ip_addr_set_zero(&dhcp->offered_ip_addr);
01190   ip_addr_set_zero(&dhcp->offered_sn_mask);
01191   ip_addr_set_zero(&dhcp->offered_gw_addr);
01192 #if LWIP_DHCP_BOOTP_FILE
01193   ip_addr_set_zero(&dhcp->offered_si_addr);
01194 #endif /* LWIP_DHCP_BOOTP_FILE */
01195   dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0;
01196   
01197   /* create and initialize the DHCP message header */
01198   result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE);
01199   if (result == ERR_OK) {
01200     dhcp_option_trailer(dhcp);
01201 
01202     pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
01203 
01204     udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
01205     dhcp_delete_msg(dhcp);
01206     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n"));
01207   } else {
01208     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n"));
01209   }
01210   dhcp->tries++;
01211   msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
01212   dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
01213   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs));
01214   /* bring the interface down */
01215   netif_set_down(netif);
01216   /* remove IP address from interface */
01217   netif_set_ipaddr(netif, IP_ADDR_ANY);
01218   netif_set_gw(netif, IP_ADDR_ANY);
01219   netif_set_netmask(netif, IP_ADDR_ANY);
01220   
01221   return result;
01222 }
01223 
01229 void
01230 dhcp_stop(struct netif *netif)
01231 {
01232   struct dhcp *dhcp;
01233   LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;);
01234   dhcp = netif->dhcp;
01235   /* Remove the flag that says this netif is handled by DHCP. */
01236   netif->flags &= ~NETIF_FLAG_DHCP;
01237 
01238   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n"));
01239   /* netif is DHCP configured? */
01240   if (dhcp != NULL) {
01241 #if LWIP_DHCP_AUTOIP_COOP
01242     if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
01243       autoip_stop(netif);
01244       dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
01245     }
01246 #endif /* LWIP_DHCP_AUTOIP_COOP */
01247 
01248     if (dhcp->pcb != NULL) {
01249       udp_remove(dhcp->pcb);
01250       dhcp->pcb = NULL;
01251     }
01252     LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL);
01253     dhcp_set_state(dhcp, DHCP_OFF);
01254   }
01255 }
01256 
01257 /*
01258  * Set the DHCP state of a DHCP client.
01259  *
01260  * If the state changed, reset the number of tries.
01261  */
01262 static void
01263 dhcp_set_state(struct dhcp *dhcp, u8_t new_state)
01264 {
01265   if (new_state != dhcp->state) {
01266     dhcp->state = new_state;
01267     dhcp->tries = 0;
01268     dhcp->request_timeout = 0;
01269   }
01270 }
01271 
01272 /*
01273  * Concatenate an option type and length field to the outgoing
01274  * DHCP message.
01275  *
01276  */
01277 static void
01278 dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len)
01279 {
01280   LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN);
01281   dhcp->msg_out->options[dhcp->options_out_len++] = option_type;
01282   dhcp->msg_out->options[dhcp->options_out_len++] = option_len;
01283 }
01284 /*
01285  * Concatenate a single byte to the outgoing DHCP message.
01286  *
01287  */
01288 static void
01289 dhcp_option_byte(struct dhcp *dhcp, u8_t value)
01290 {
01291   LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN);
01292   dhcp->msg_out->options[dhcp->options_out_len++] = value;
01293 }
01294 
01295 static void
01296 dhcp_option_short(struct dhcp *dhcp, u16_t value)
01297 {
01298   LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN);
01299   dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8);
01300   dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU);
01301 }
01302 
01303 static void
01304 dhcp_option_long(struct dhcp *dhcp, u32_t value)
01305 {
01306   LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN);
01307   dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24);
01308   dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16);
01309   dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8);
01310   dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL));
01311 }
01312 
01323 static err_t
01324 dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p)
01325 {
01326   u8_t *options;
01327   u16_t offset;
01328   u16_t offset_max;
01329   u16_t options_idx;
01330   u16_t options_idx_max;
01331   struct pbuf *q;
01332   int parse_file_as_options = 0;
01333   int parse_sname_as_options = 0;
01334 
01335   /* clear received options */
01336   dhcp_clear_all_options(dhcp);
01337   /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */
01338   if (p->len < DHCP_SNAME_OFS) {
01339     return ERR_BUF;
01340   }
01341   dhcp->msg_in = (struct dhcp_msg *)p->payload;
01342 #if LWIP_DHCP_BOOTP_FILE
01343   /* clear boot file name */
01344   dhcp->boot_file_name[0] = 0;
01345 #endif /* LWIP_DHCP_BOOTP_FILE */
01346 
01347   /* parse options */
01348 
01349   /* start with options field */
01350   options_idx = DHCP_OPTIONS_OFS;
01351   /* parse options to the end of the received packet */
01352   options_idx_max = p->tot_len;
01353 again:
01354   q = p;
01355   while((q != NULL) && (options_idx >= q->len)) {
01356     options_idx -= q->len;
01357     options_idx_max -= q->len;
01358     q = q->next;
01359   }
01360   if (q == NULL) {
01361     return ERR_BUF;
01362   }
01363   offset = options_idx;
01364   offset_max = options_idx_max;
01365   options = (u8_t*)q->payload;
01366   /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
01367   while((q != NULL) && (options[offset] != DHCP_OPTION_END) && (offset < offset_max)) {
01368     u8_t op = options[offset];
01369     u8_t len;
01370     u8_t decode_len = 0;
01371     int decode_idx = -1;
01372     u16_t val_offset = offset + 2;
01373     /* len byte might be in the next pbuf */
01374     if (offset + 1 < q->len) {
01375       len = options[offset + 1];
01376     } else {
01377       len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0);
01378     }
01379     /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
01380     decode_len = len;
01381     switch(op) {
01382       /* case(DHCP_OPTION_END): handled above */
01383       case(DHCP_OPTION_PAD):
01384         /* special option: no len encoded */
01385         decode_len = len = 0;
01386         /* will be increased below */
01387         offset--;
01388         break;
01389       case(DHCP_OPTION_SUBNET_MASK):
01390         LWIP_ASSERT("len == 4", len == 4);
01391         decode_idx = DHCP_OPTION_IDX_SUBNET_MASK;
01392         break;
01393       case(DHCP_OPTION_ROUTER):
01394         decode_len = 4; /* only copy the first given router */
01395         LWIP_ASSERT("len >= decode_len", len >= decode_len);
01396         decode_idx = DHCP_OPTION_IDX_ROUTER;
01397         break;
01398       case(DHCP_OPTION_DNS_SERVER):
01399         /* special case: there might be more than one server */
01400         LWIP_ASSERT("len % 4 == 0", len % 4 == 0);
01401         /* limit number of DNS servers */
01402         decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS);
01403         LWIP_ASSERT("len >= decode_len", len >= decode_len);
01404         decode_idx = DHCP_OPTION_IDX_DNS_SERVER;
01405         break;
01406       case(DHCP_OPTION_LEASE_TIME):
01407         LWIP_ASSERT("len == 4", len == 4);
01408         decode_idx = DHCP_OPTION_IDX_LEASE_TIME;
01409         break;
01410       case(DHCP_OPTION_OVERLOAD):
01411         LWIP_ASSERT("len == 1", len == 1);
01412         decode_idx = DHCP_OPTION_IDX_OVERLOAD;
01413         break;
01414       case(DHCP_OPTION_MESSAGE_TYPE):
01415         LWIP_ASSERT("len == 1", len == 1);
01416         decode_idx = DHCP_OPTION_IDX_MSG_TYPE;
01417         break;
01418       case(DHCP_OPTION_SERVER_ID):
01419         LWIP_ASSERT("len == 4", len == 4);
01420         decode_idx = DHCP_OPTION_IDX_SERVER_ID;
01421         break;
01422       case(DHCP_OPTION_T1):
01423         LWIP_ASSERT("len == 4", len == 4);
01424         decode_idx = DHCP_OPTION_IDX_T1;
01425         break;
01426       case(DHCP_OPTION_T2):
01427         LWIP_ASSERT("len == 4", len == 4);
01428         decode_idx = DHCP_OPTION_IDX_T2;
01429         break;
01430       default:
01431         decode_len = 0;
01432         LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", op));
01433         break;
01434     }
01435     offset += len + 2;
01436     if (decode_len > 0) {
01437       u32_t value = 0;
01438       u16_t copy_len;
01439 decode_next:
01440       LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX);
01441       LWIP_ASSERT("option already decoded", !dhcp_option_given(dhcp, decode_idx));
01442       copy_len = LWIP_MIN(decode_len, 4);
01443       pbuf_copy_partial(q, &value, copy_len, val_offset);
01444       if (decode_len > 4) {
01445         /* decode more than one u32_t */
01446         LWIP_ASSERT("decode_len % 4 == 0", decode_len % 4 == 0);
01447         dhcp_got_option(dhcp, decode_idx);
01448         dhcp_set_option_value(dhcp, decode_idx, htonl(value));
01449         decode_len -= 4;
01450         val_offset += 4;
01451         decode_idx++;
01452         goto decode_next;
01453       } else if (decode_len == 4) {
01454         value = ntohl(value);
01455       } else {
01456         LWIP_ASSERT("invalid decode_len", decode_len == 1);
01457         value = ((u8_t*)&value)[0];
01458       }
01459       dhcp_got_option(dhcp, decode_idx);
01460       dhcp_set_option_value(dhcp, decode_idx, value);
01461     }
01462     if (offset >= q->len) {
01463       offset -= q->len;
01464       offset_max -= q->len;
01465       q = q->next;
01466       options = (u8_t*)q->payload;
01467     }
01468   }
01469   /* is this an overloaded message? */
01470   if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) {
01471     u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD);
01472     dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD);
01473     if (overload == DHCP_OVERLOAD_FILE) {
01474       parse_file_as_options = 1;
01475       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n"));
01476     } else if (overload == DHCP_OVERLOAD_SNAME) {
01477       parse_sname_as_options = 1;
01478       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n"));
01479     } else if (overload == DHCP_OVERLOAD_SNAME_FILE) {
01480       parse_sname_as_options = 1;
01481       parse_file_as_options = 1;
01482       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n"));
01483     } else {
01484       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload));
01485     }
01486 #if LWIP_DHCP_BOOTP_FILE
01487     if (!parse_file_as_options) {
01488       /* only do this for ACK messages */
01489       if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) &&
01490         (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK))
01491       /* copy bootp file name, don't care for sname (server hostname) */
01492       pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS);
01493       /* make sure the string is really NULL-terminated */
01494       dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0;
01495     }
01496 #endif /* LWIP_DHCP_BOOTP_FILE */
01497   }
01498   if (parse_file_as_options) {
01499     /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */
01500     parse_file_as_options = 0;
01501     options_idx = DHCP_FILE_OFS;
01502     options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN;
01503     goto again;
01504   } else if (parse_sname_as_options) {
01505     parse_sname_as_options = 0;
01506     options_idx = DHCP_SNAME_OFS;
01507     options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN;
01508     goto again;
01509   }
01510   return ERR_OK;
01511 }
01512 
01516 static void
01517 dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
01518 {
01519   struct netif *netif = (struct netif *)arg;
01520   struct dhcp *dhcp = netif->dhcp;
01521   struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload;
01522   u8_t msg_type;
01523   u8_t i;
01524   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,
01525     ip4_addr1_16(addr), ip4_addr2_16(addr), ip4_addr3_16(addr), ip4_addr4_16(addr), port));
01526   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
01527   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len));
01528   /* prevent warnings about unused arguments */
01529   LWIP_UNUSED_ARG(pcb);
01530   LWIP_UNUSED_ARG(addr);
01531   LWIP_UNUSED_ARG(port);
01532 
01533   LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL);
01534 
01535   if (p->len < DHCP_MIN_REPLY_LEN) {
01536     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n"));
01537     goto free_pbuf_and_return;
01538   }
01539 
01540   if (reply_msg->op != DHCP_BOOTREPLY) {
01541     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));
01542     goto free_pbuf_and_return;
01543   }
01544   /* iterate through hardware address and match against DHCP message */
01545   for (i = 0; i < netif->hwaddr_len; i++) {
01546     if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
01547       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
01548         ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
01549         (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i]));
01550       goto free_pbuf_and_return;
01551     }
01552   }
01553   /* match transaction ID against what we expected */
01554   if (ntohl(reply_msg->xid) != dhcp->xid) {
01555     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
01556       ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid));
01557     goto free_pbuf_and_return;
01558   }
01559   /* option fields could be unfold? */
01560   if (dhcp_parse_reply(dhcp, p) != ERR_OK) {
01561     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
01562       ("problem unfolding DHCP message - too short on memory?\n"));
01563     goto free_pbuf_and_return;
01564   }
01565 
01566   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n"));
01567   /* obtain pointer to DHCP message type */
01568   if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) {
01569     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
01570     goto free_pbuf_and_return;
01571   }
01572 
01573   /* read DHCP message type */
01574   msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE);
01575   /* message type is DHCP ACK? */
01576   if (msg_type == DHCP_ACK) {
01577     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n"));
01578     /* in requesting state? */
01579     if (dhcp->state == DHCP_REQUESTING) {
01580       dhcp_handle_ack(netif);
01581 #if DHCP_DOES_ARP_CHECK
01582       /* check if the acknowledged lease address is already in use */
01583       dhcp_check(netif);
01584 #else
01585       /* bind interface to the acknowledged lease address */
01586       dhcp_bind(netif);
01587 #endif
01588     }
01589     /* already bound to the given lease address? */
01590     else if ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING)) {
01591       dhcp_bind(netif);
01592     }
01593   }
01594   /* received a DHCP_NAK in appropriate state? */
01595   else if ((msg_type == DHCP_NAK) &&
01596     ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) ||
01597      (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING  ))) {
01598     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n"));
01599     dhcp_handle_nak(netif);
01600   }
01601   /* received a DHCP_OFFER in DHCP_SELECTING state? */
01602   else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) {
01603     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_SELECTING state\n"));
01604     dhcp->request_timeout = 0;
01605     /* remember offered lease */
01606     dhcp_handle_offer(netif);
01607   }
01608 free_pbuf_and_return:
01609   dhcp->msg_in = NULL;
01610   pbuf_free(p);
01611 }
01612 
01620 static err_t
01621 dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type)
01622 {
01623   u16_t i;
01624 #ifndef DHCP_GLOBAL_XID
01625 
01629   static u32_t xid = 0xABCD0000;
01630 #else
01631   static u32_t xid;
01632   static u8_t xid_initialised = 0;
01633   if (!xid_initialised) {
01634     xid = DHCP_GLOBAL_XID;
01635     xid_initialised = !xid_initialised;
01636   }
01637 #endif
01638   LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG;);
01639   LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL;);
01640   LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL);
01641   LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL);
01642   dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
01643   if (dhcp->p_out == NULL) {
01644     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
01645       ("dhcp_create_msg(): could not allocate pbuf\n"));
01646     return ERR_MEM;
01647   }
01648   LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg",
01649            (dhcp->p_out->len >= sizeof(struct dhcp_msg)));
01650 
01651   /* reuse transaction identifier in retransmissions */
01652   if (dhcp->tries == 0) {
01653       xid++;
01654   }
01655   dhcp->xid = xid;
01656   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
01657               ("transaction id xid(%"X32_F")\n", xid));
01658 
01659   dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload;
01660 
01661   dhcp->msg_out->op = DHCP_BOOTREQUEST;
01662   /* TODO: make link layer independent */
01663   dhcp->msg_out->htype = DHCP_HTYPE_ETH;
01664   dhcp->msg_out->hlen = netif->hwaddr_len;
01665   dhcp->msg_out->hops = 0;
01666   dhcp->msg_out->xid = htonl(dhcp->xid);
01667   dhcp->msg_out->secs = 0;
01668   /* we don't need the broadcast flag since we can receive unicast traffic
01669      before being fully configured! */
01670   dhcp->msg_out->flags = 0;
01671   ip_addr_set_zero(&dhcp->msg_out->ciaddr);
01672   /* set ciaddr to netif->ip_addr based on message_type and state */
01673   if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) ||
01674       ((message_type == DHCP_REQUEST) && /* DHCP_BOUND not used for sending! */
01675        ((dhcp->state==DHCP_RENEWING) || dhcp->state==DHCP_REBINDING))) {
01676     ip_addr_copy(dhcp->msg_out->ciaddr, netif->ip_addr);
01677   }
01678   ip_addr_set_zero(&dhcp->msg_out->yiaddr);
01679   ip_addr_set_zero(&dhcp->msg_out->siaddr);
01680   ip_addr_set_zero(&dhcp->msg_out->giaddr);
01681   for (i = 0; i < DHCP_CHADDR_LEN; i++) {
01682     /* copy netif hardware address, pad with zeroes */
01683     dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0/* pad byte*/;
01684   }
01685   for (i = 0; i < DHCP_SNAME_LEN; i++) {
01686     dhcp->msg_out->sname[i] = 0;
01687   }
01688   for (i = 0; i < DHCP_FILE_LEN; i++) {
01689     dhcp->msg_out->file[i] = 0;
01690   }
01691   dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
01692   dhcp->options_out_len = 0;
01693   /* fill options field with an incrementing array (for debugging purposes) */
01694   for (i = 0; i < DHCP_OPTIONS_LEN; i++) {
01695     dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */
01696   }
01697   /* Add option MESSAGE_TYPE */
01698   dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
01699   dhcp_option_byte(dhcp, message_type);
01700   return ERR_OK;
01701 }
01702 
01708 static void
01709 dhcp_delete_msg(struct dhcp *dhcp)
01710 {
01711   LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return;);
01712   LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL);
01713   LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL);
01714   if (dhcp->p_out != NULL) {
01715     pbuf_free(dhcp->p_out);
01716   }
01717   dhcp->p_out = NULL;
01718   dhcp->msg_out = NULL;
01719 }
01720 
01729 static void
01730 dhcp_option_trailer(struct dhcp *dhcp)
01731 {
01732   LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;);
01733   LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL);
01734   LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
01735   dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
01736   /* packet is too small, or not 4 byte aligned? */
01737   while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) {
01738     /* 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)); */
01739     LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
01740     /* add a fill/padding byte */
01741     dhcp->msg_out->options[dhcp->options_out_len++] = 0;
01742   }
01743 }
01744 
01745 #endif /* LWIP_DHCP */

Generated on Sun May 27 2012 04:36:01 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.