Pehr Hovey / Mbed 2 deprecated mbed_osc

Dependencies:   mbed

Committer:
pehrhovey
Date:
Wed Mar 17 03:17:38 2010 +0000
Revision:
0:439354122597

        

Who changed what in which revision?

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