Official mbed lwIP library (version 1.4.0)

Dependents:   LwIPNetworking NetServicesMin EthernetInterface EthernetInterface_RSF ... more

Legacy Networking Libraries

This is an mbed 2 networking library. For mbed OS 5, lwip has been integrated with built-in networking interfaces. The networking libraries have been revised to better support additional network stacks and thread safety here.

This library is based on the code of lwIP v1.4.0

Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
All rights reserved. 

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission. 

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
Committer:
mbed_official
Date:
Mon Mar 14 16:15:36 2016 +0000
Revision:
20:08f08bfc3f3d
Parent:
11:4b3f6f8b92d2
Synchronized with git revision fec574a5ed6db26aca1b13992ff271bf527d4a0d

Full URL: https://github.com/mbedmicro/mbed/commit/fec574a5ed6db26aca1b13992ff271bf527d4a0d/

Increased allocated netbufs to handle DTLS handshakes

Who changed what in which revision?

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