Some quick code to use UDP-only (no TCP) with mBed. Echos received packets and sends packets when a button is pressed

Dependencies:   mbed

Committer:
pehrhovey
Date:
Sun Mar 14 00:54:12 2010 +0000
Revision:
0:a548a085de55

        

Who changed what in which revision?

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