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