A version of LWIP, provided for backwards compatibility.

Dependents:   AA_DemoBoard DemoBoard HelloServerDemo DemoBoard_RangeIndicator ... more

Committer:
root@mbed.org
Date:
Tue May 08 15:32:10 2012 +0100
Revision:
0:5e1631496985
initial commit

Who changed what in which revision?

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