• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * @file
3  * DHCP client API
4  */
5 
6 /*
7  * Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@gmx.net>
8  * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification,
12  * are permitted provided that the following conditions are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright notice,
15  *    this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright notice,
17  *    this list of conditions and the following disclaimer in the documentation
18  *    and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31  * OF SUCH DAMAGE.
32  *
33  * This file is part of the lwIP TCP/IP stack.
34  *
35  * Author: Leon Woestenberg <leon.woestenberg@gmx.net>
36  *
37  */
38 #ifndef LWIP_HDR_DHCP_H
39 #define LWIP_HDR_DHCP_H
40 
41 #include "lwip/opt.h"
42 
43 #if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */
44 
45 #include "lwip/netif.h"
46 #include "lwip/udp.h"
47 #include "lwip/dhcps.h"
48 #include "lwip/prot/dhcp.h"
49 
50 #ifdef __cplusplus
51 extern "C" {
52 #endif
53 
54 #ifndef LWIP_DHCP_NATIVE_IDX
55 #define LWIP_DHCP_NATIVE_IDX 0
56 #endif
57 
58 #ifndef LWIP_DHCP_ANNOUNCE_NUM
59 #define LWIP_DHCP_ANNOUNCE_NUM 2
60 #endif
61 
62 #ifndef LWIP_DHCP_ANNOUNCE_INTERVAL
63 #define LWIP_DHCP_ANNOUNCE_INTERVAL 2 /* seconds */
64 #endif
65 
66 #if LWIP_DHCP_SUBSTITUTE
67 struct dhcp_clients_info;
68 #ifndef DHCP_CLIENT_NUM
69 #define DHCP_CLIENT_NUM 256
70 #endif
71 typedef u16_t dhcp_num_t;
72 #define DHCP_NUM_F "hu"
73 #else
74 #ifndef DHCP_CLIENT_NUM
75 #define DHCP_CLIENT_NUM 1
76 #endif
77 typedef u32_t dhcp_num_t;
78 #define DHCP_NUM_F "u"
79 #endif /* LWIP_DHCP_SUBSTITUTE */
80 
81 #define IPV4_ADDRESS_PREFIX_CLASS_A 127
82 #define IPV4_ADDRESS_PREFIX_CLASS_C 192
83 
84 #define DHCP_XID(_xid, _mac, _mac_len, _dhcp_xid) do { \
85   u8_t *_p = (u8_t *)(&(_xid)); \
86   _p[0] = (_mac)[(_mac_len) - 3]; \
87   _p[1] = (_mac)[(_mac_len) - 2]; \
88   _p[2] = (_mac)[(_mac_len) - 1]; \
89   _p[3] = _dhcp_xid; \
90 } while (0)
91 
92 #define DHCP_HOST_TO_IP(_ip, _serv_ip, _mask, _host) do { \
93   u32_t _ipaddr = (u32_t)(_host); \
94   (_ip) = (((_serv_ip) & (_mask)) | lwip_htonl(_ipaddr)); \
95 } while (0)
96 
97 #define DHCP_IP_TO_HOST(_host, _ip, _mask) do { \
98   (_host) = (dhcp_num_t)(lwip_ntohl(_ip) & (~lwip_ntohl(_mask))); \
99 } while (0)
100 
101 /* more related events should be defined here */
102 #define DHCP_EVENT_HW 0x01
103 
104 /** period (in seconds) of the application calling dhcp_coarse_tmr() */
105 #define DHCP_COARSE_TIMER_SECS  10
106 /** period (in milliseconds) of the application calling dhcp_coarse_tmr() */
107 #define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL)
108 /** period (in milliseconds) of the application calling dhcp_fine_tmr() */
109 #define DHCP_FINE_TIMER_MSECS   500
110 
111 #ifndef DHCP_DISCOVER_RETRANSMIT_INTERVAL
112 #define DHCP_DISCOVER_RETRANSMIT_INTERVAL 250
113 #endif
114 
115 #define DHCP_BOOT_FILE_LEN      128U
116 #define DHCP_BROADCAST_FLAG     0x8000
117 /* AutoIP cooperation flags (struct dhcp.autoip_coop_state) */
118 typedef enum {
119   DHCP_AUTOIP_COOP_STATE_OFF  = 0,
120   DHCP_AUTOIP_COOP_STATE_ON   = 1
121 } dhcp_autoip_coop_state_enum_t;
122 
123 /** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU
124  * MTU is checked to be big enough in dhcp_start */
125 #define DHCP_MAX_MSG_LEN(netif)        (netif->mtu)
126 #define DHCP_MAX_MSG_LEN_MIN_REQUIRED  576
127 
128 #if LWIP_DHCP_VENDOR_CLASS_IDENTIFIER
129 struct vci_info {
130   /* buffer for vendor class identifier information */
131   char vci[DHCP_VCI_MAX_LEN];
132   /* real length of vci */
133   u8_t vci_len;
134 };
135 
136 err_t dhcp_set_vci(const char *vci, u8_t vci_len);
137 err_t dhcp_get_vci(char *vci, u8_t *vci_len);
138 #endif /* LWIP_DHCP_VENDOR_CLASS_IDENTIFIER */
139 
140 /** Minimum length for reply before packet is parsed */
141 #define DHCP_MIN_REPLY_LEN             44
142 
143 #define REBOOT_TRIES                2
144 
145 #if LWIP_DNS && LWIP_DHCP_MAX_DNS_SERVERS
146 #if DNS_MAX_SERVERS > LWIP_DHCP_MAX_DNS_SERVERS
147 #define LWIP_DHCP_PROVIDE_DNS_SERVERS LWIP_DHCP_MAX_DNS_SERVERS
148 #else
149 #define LWIP_DHCP_PROVIDE_DNS_SERVERS DNS_MAX_SERVERS
150 #endif
151 #else
152 #define LWIP_DHCP_PROVIDE_DNS_SERVERS 0
153 #endif
154 
155 #ifndef LWIP_DHCP_INPUT_ERROR
156 #define LWIP_DHCP_INPUT_ERROR(message, expression, handler) do { if (!(expression)) { \
157   handler;} } while(0)
158 #endif
159 
160 /** Option handling: options are parsed in dhcp_parse_reply
161  * and saved in an array where other functions can load them from.
162  * This might be moved into the struct dhcp (not necessarily since
163  * lwIP is single-threaded and the array is only used while in recv
164  * callback). */
165 enum dhcp_option_idx {
166   DHCP_OPTION_IDX_OVERLOAD = 0,
167   DHCP_OPTION_IDX_MSG_TYPE,
168   DHCP_OPTION_IDX_SERVER_ID,
169   DHCP_OPTION_IDX_LEASE_TIME,
170   DHCP_OPTION_IDX_T1,
171   DHCP_OPTION_IDX_T2,
172   DHCP_OPTION_IDX_SUBNET_MASK,
173   DHCP_OPTION_IDX_ROUTER,
174 #if LWIP_DHCP_PROVIDE_DNS_SERVERS
175   DHCP_OPTION_IDX_DNS_SERVER,
176   DHCP_OPTION_IDX_DNS_SERVER_LAST = DHCP_OPTION_IDX_DNS_SERVER + LWIP_DHCP_PROVIDE_DNS_SERVERS - 1,
177 #endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
178 #if LWIP_DHCP_GET_NTP_SRV
179   DHCP_OPTION_IDX_NTP_SERVER,
180   DHCP_OPTION_IDX_NTP_SERVER_LAST = DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS - 1,
181 #endif /* LWIP_DHCP_GET_NTP_SRV */
182   DHCP_OPTION_IDX_REQUESTED_IP,
183 #if LWIP_DHCPS_AGENT_INFO
184   DHCP_OPTION_IDX_AGENT_INFO,
185 #endif
186   DHCP_OPTION_IDX_MAX
187 };
188 
189 struct dhcp_state {
190   /* transaction identifier of last sent request */
191   u8_t xid;
192   /* retries of current request <= 255 */
193   u8_t tries;
194   u16_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */
195   u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */
196   u16_t re_time;  /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew/rebind try */
197   u8_t state:4; /* current DHCP state machine state */
198 #if (NETIF_MAX_HWADDR_LEN > 7)
199 #error "max hwaddr length should not greater than 7 in this implementation"
200 #endif
201   u8_t hwaddr_len:3;
202 #if LWIP_DHCP_SUBSTITUTE_MMBR
203   u8_t addr_not_dup_check:1;
204 #endif
205   /* idx in NAT64 table */
206   dhcp_num_t idx;
207   /* host part of IP */
208   dhcp_num_t offered_ip_addr;
209 };
210 
211 struct dhcp_client {
212   u16_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */
213   u16_t t1_timeout;  /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */
214   u16_t t2_timeout;  /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */
215   ip_addr_t server_ip_addr; /* dhcp server address that offered this lease (ip_addr_t because passed to UDP) */
216   u8_t subnet_mask_given;
217   ip4_addr_t offered_sn_mask;
218   ip4_addr_t offered_gw_addr;
219   ip4_addr_t relay_ip;
220   u32_t offered_t0_lease; /* lease period (in seconds) */
221   u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */
222   u32_t offered_t2_rebind; /* recommended rebind time (usually 87.5 of lease period)  */
223 
224   /* incoming msg */
225   struct dhcp_msg *msg_in;
226   struct pbuf *p_out; /* pbuf of outcoming msg */
227   struct dhcp_msg *msg_out; /* outgoing msg */
228   u16_t options_out_len; /* outgoing msg options length */
229 
230   u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
231 #if LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS
232   /* the number of concurrent requesting IPv4 address nodes */
233   dhcp_num_t rqst_cli_cnt;
234 #endif
235   dhcp_num_t cli_cnt;
236   /* cli_idx = LWIP_DHCP_NATIVE_IDX always means the client for the netif */
237   dhcp_num_t cli_idx;
238   struct dhcp_state states[DHCP_CLIENT_NUM];
239 };
240 
241 struct dhcp {
242   /* track PCB allocation state */
243   u8_t pcb_allocated;
244 #if LWIP_DHCP_AUTOIP_COOP
245   u8_t autoip_coop_state;
246 #endif
247 
248 #if LWIP_DHCP_BOOTP_FILE
249   ip4_addr_t offered_si_addr;
250   char boot_file_name[DHCP_BOOT_FILE_LEN];
251 #endif /* LWIP_DHCP_BOOTPFILE */
252 #if LWIP_DHCP_SUBSTITUTE
253   u8_t flags;
254   struct dhcp_clients_info *clis_info;
255 #endif
256   struct dhcp_client client;
257 };
258 
259 #if LWIP_DHCPS
260 struct dyn_lease_addr {
261   u8_t cli_hwaddr[DHCP_CHADDR_LEN];
262   u32_t flags;
263   u32_t leasetime;
264   u32_t proposed_leasetime;
265   ip4_addr_t cli_addr;
266 };
267 
268 struct dhcps {
269   struct udp_pcb *pcb;
270   struct dyn_lease_addr leasearr[LWIP_DHCPS_MAX_LEASE];
271   u8_t pcb_allocated;
272   u8_t lease_num;
273   struct netif *netif;
274   ip4_addr_t start_addr;
275   ip4_addr_t end_addr;
276 #if LWIP_DHCPS_AGENT_INFO
277   struct pbuf *p_in; /* pbuf of incoming msg */
278 #endif
279 };
280 #endif
281 
282 void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp);
283 /** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */
284 void dhcp_remove_struct(struct netif *netif);
285 void dhcp_cleanup(struct netif *netif);
286 err_t dhcp_is_bound(struct netif *netif);
287 err_t dhcp_start(struct netif *netif);
288 err_t dhcp_renew(struct netif *netif);
289 err_t dhcp_release(struct netif *netif);
290 void dhcp_stop(struct netif *netif);
291 void dhcp_release_and_stop(struct netif *netif);
292 void dhcp_inform(struct netif *netif);
293 void dhcp_network_changed(struct netif *netif);
294 #if DHCP_DOES_ARP_CHECK
295 void dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr);
296 #endif
297 u8_t dhcp_supplied_address(const struct netif *netif);
298 /* to be called every minute */
299 void dhcp_coarse_tmr(void);
300 /* to be called every half second */
301 void dhcp_fine_tmr(void);
302 
303 #if LWIP_LOWPOWER
304 u32_t dhcp_coarse_tmr_tick(void);
305 u32_t dhcp_fine_tmr_tick(void);
306 #endif
307 
308 #if LWIP_DHCP_GET_NTP_SRV
309 /** This function must exist, in other to add offered NTP servers to
310  * the NTP (or SNTP) engine.
311  * See LWIP_DHCP_MAX_NTP_SERVERS */
312 extern void dhcp_set_ntp_servers(u8_t num_ntp_servers, const ip4_addr_t* ntp_server_addrs);
313 #endif /* LWIP_DHCP_GET_NTP_SRV */
314 
315 #define netif_dhcp_data(netif) ((struct dhcp*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP))
316 
317 #if LWIP_DHCP_SUBSTITUTE
318 struct dhcp_client_info {
319   ip4_addr_t ip4addr;
320   ip6_addr_t ip6addr;
321   u8_t mac[NETIF_MAX_HWADDR_LEN];
322   u8_t mac_len;
323 };
324 
325 struct dhcp_client_mac_info {
326   u8_t mac[NETIF_MAX_HWADDR_LEN];
327   u8_t mac_len;
328 };
329 
330 struct dhcp_clients_info {
331   dhcp_num_t num;
332   struct dhcp_client_mac_info clis[0];
333 };
334 
335 #if LWIP_ARP
336 void dhcp_events_record(struct netif *netif, u8_t flags);
337 void dhcp_events_trigger(struct netif *netif);
338 #endif /* LWIP_ARP */
339 err_t dhcp_substitute_start(struct netif *netif, dhcp_num_t mac_idx, u32_t pref_ipv4);
340 void dhcp_substitute_stop(struct netif *netif, dhcp_num_t mac_idx, u8_t now);
341 err_t dhcp_substitute_idx_to_ip(struct netif *netif, dhcp_num_t idx, ip4_addr_t *ip);
342 err_t dhcp_clients_info_get(struct netif *netif, void *arg);
343 err_t dhcp_clients_info_free(struct netif *netif, void *arg);
344 err_t dhcp_client_info_find(struct netif *netif, void *cli_info);
345 #if LWIP_ENABLE_BASIC_SHELL_CMD
346 s32_t dhcp_netif_addr_clients_check(const struct netif *netif, const ip4_addr_t *ipaddr);
347 #endif /* LWIP_ENABLE_BASIC_SHELL_CMD */
348 #if LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS
349 err_t dhcp_set_max_concurrent_num(struct netif *netif, u16_t dhcp_max_concurrent_num);
350 #endif
351 #endif /* LWIP_DHCP_SUBSTITUTE */
352 
353 #ifdef __cplusplus
354 }
355 #endif
356 
357 #endif /* LWIP_DHCP */
358 
359 #endif /*LWIP_HDR_DHCP_H*/
360