• 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 #if defined (__cplusplus) && __cplusplus
50 extern "C" {
51 #endif
52 
53 #ifndef LWIP_DHCP_NATIVE_IDX
54 #define LWIP_DHCP_NATIVE_IDX 0
55 #endif
56 
57 #ifndef LWIP_DHCP_ANNOUNCE_NUM
58 #define LWIP_DHCP_ANNOUNCE_NUM 2
59 #endif
60 
61 #ifndef LWIP_DHCP_ANNOUNCE_INTERVAL
62 #define LWIP_DHCP_ANNOUNCE_INTERVAL 2 /* seconds */
63 #endif
64 
65 #if LWIP_DHCP_SUBSTITUTE
66 struct dhcp_clients_info;
67 #ifndef DHCP_CLIENT_NUM
68 #define DHCP_CLIENT_NUM 256
69 #endif
70 typedef u16_t dhcp_num_t;
71 #define DHCP_NUM_F "hu"
72 #else
73 #ifndef DHCP_CLIENT_NUM
74 #define DHCP_CLIENT_NUM 1
75 #endif
76 typedef u32_t dhcp_num_t;
77 #define DHCP_NUM_F "u"
78 #endif /* LWIP_DHCP_SUBSTITUTE */
79 
80 #define IPV4_ADDRESS_PREFIX_CLASS_A 127
81 #define IPV4_ADDRESS_PREFIX_CLASS_C 192
82 
83 #define DHCP_XID(_xid, _mac, _mac_len, _dhcp_xid) do { \
84   u8_t *_p = (u8_t *)(&(_xid)); \
85   _p[0] = (_mac)[(_mac_len) - 3]; \
86   _p[1] = (_mac)[(_mac_len) - 2]; \
87   _p[2] = (_mac)[(_mac_len) - 1]; \
88   _p[3] = _dhcp_xid; \
89 } while (0)
90 
91 #define DHCP_HOST_TO_IP(_ip, _serv_ip, _mask, _host) do { \
92   u32_t _ipaddr = (u32_t)(_host); \
93   (_ip) = (((_serv_ip) & (_mask)) | lwip_htonl(_ipaddr)); \
94 } while (0)
95 
96 #define DHCP_IP_TO_HOST(_host, _ip, _mask) do { \
97   (_host) = (dhcp_num_t)(lwip_ntohl(_ip) & (~lwip_ntohl(_mask))); \
98 } while (0)
99 
100 /* more related events should be defined here */
101 #define DHCP_EVENT_HW 0x01
102 
103 /* period (in seconds) of the application calling dhcp_coarse_tmr() */
104 #define DHCP_COARSE_TIMER_SECS  10
105 /* period (in milliseconds) of the application calling dhcp_coarse_tmr() */
106 #define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL)
107 /* period (in milliseconds) of the application calling dhcp_fine_tmr() */
108 #define DHCP_FINE_TIMER_MSECS   500
109 
110 #ifndef DHCP_DISCOVER_RETRANSMIT_INTERVAL
111 #define DHCP_DISCOVER_RETRANSMIT_INTERVAL 250
112 #endif
113 
114 #define DHCP_BOOT_FILE_LEN      128U
115 #define DHCP_BROADCAST_FLAG 0x8000
116 /* AutoIP cooperation flags (struct dhcp.autoip_coop_state) */
117 typedef enum {
118   DHCP_AUTOIP_COOP_STATE_OFF  = 0,
119   DHCP_AUTOIP_COOP_STATE_ON   = 1
120 } dhcp_autoip_coop_state_enum_t;
121 
122 /*
123  * DHCP_OPTION_MAX_MSG_SIZE is set to the MTU
124  * MTU is checked to be big enough in dhcp_start
125  */
126 #define DHCP_MAX_MSG_LEN(netif)        (netif->mtu)
127 #define DHCP_MAX_MSG_LEN_MIN_REQUIRED  576
128 
129 #if LWIP_DHCP_VENDOR_CLASS_IDENTIFIER
130 struct vci_info {
131   /* buffer for vendor class identifier information */
132   char vci[DHCP_VCI_MAX_LEN];
133   /* real length of vci */
134   u8_t vci_len;
135   /* pad for performance optimization */
136   char pad[24];
137 };
138 
139 err_t dhcp_set_vci(char *vci, u8_t vci_len);
140 #if LWIP_DHCP_GET_VENDOR_CLASS_IDENTIFIER
141 err_t dhcp_get_vci(char *vci, u8_t *vci_len);
142 #endif /* LWIP_DHCP_GET_VENDOR_CLASS_IDENTIFIER */
143 #endif /* LWIP_DHCP_VENDOR_CLASS_IDENTIFIER */
144 
145 /** Minimum length for reply before packet is parsed */
146 #define DHCP_MIN_REPLY_LEN             44
147 
148 #define REBOOT_TRIES                2
149 
150 #if LWIP_DNS && LWIP_DHCP_MAX_DNS_SERVERS
151 #if DNS_MAX_SERVERS > LWIP_DHCP_MAX_DNS_SERVERS
152 #define LWIP_DHCP_PROVIDE_DNS_SERVERS LWIP_DHCP_MAX_DNS_SERVERS
153 #else
154 #define LWIP_DHCP_PROVIDE_DNS_SERVERS DNS_MAX_SERVERS
155 #endif
156 #else
157 #define LWIP_DHCP_PROVIDE_DNS_SERVERS 0
158 #endif
159 
160 /*
161  * Option handling: options are parsed in dhcp_parse_reply
162  * and saved in an array where other functions can load them from.
163  * This might be moved into the struct dhcp (not necessarily since
164  * lwIP is single-threaded and the array is only used while in recv
165  * callback).
166  */
167 enum dhcp_option_idx {
168   DHCP_OPTION_IDX_OVERLOAD = 0,
169   DHCP_OPTION_IDX_MSG_TYPE,
170   DHCP_OPTION_IDX_SERVER_ID,
171   DHCP_OPTION_IDX_LEASE_TIME,
172   DHCP_OPTION_IDX_T1,
173   DHCP_OPTION_IDX_T2,
174   DHCP_OPTION_IDX_SUBNET_MASK,
175   DHCP_OPTION_IDX_ROUTER,
176 #if LWIP_DHCP_PROVIDE_DNS_SERVERS
177   DHCP_OPTION_IDX_DNS_SERVER,
178   DHCP_OPTION_IDX_DNS_SERVER_LAST = DHCP_OPTION_IDX_DNS_SERVER + LWIP_DHCP_PROVIDE_DNS_SERVERS - 1,
179 #endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
180 #if LWIP_DHCP_GET_NTP_SRV
181   DHCP_OPTION_IDX_NTP_SERVER,
182   DHCP_OPTION_IDX_NTP_SERVER_LAST = DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS - 1,
183 #endif /* LWIP_DHCP_GET_NTP_SRV */
184   DHCP_OPTION_IDX_REQUESTED_IP,
185 #if LWIP_DHCPS_AGENT_INFO
186   DHCP_OPTION_IDX_AGENT_INFO,
187 #endif
188   DHCP_OPTION_IDX_MAX
189 };
190 
191 struct dhcp_state {
192   /* transaction identifier of last sent request */
193   u8_t xid;
194   /* retries of current request <= 255 */
195   u8_t tries;
196   u16_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */
197   u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */
198   u16_t re_time;  /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew/rebind try */
199   /* current DHCP state machine state */
200   u8_t state: 4;
201   u8_t hwaddr_len: 4;
202   /* idx in NAT64 table */
203   dhcp_num_t idx;
204   /* host part of IP */
205   dhcp_num_t offered_ip_addr;
206 };
207 
208 struct dhcp_client {
209   u16_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */
210   u16_t t1_timeout;  /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */
211   u16_t t2_timeout;  /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */
212   ip_addr_t server_ip_addr; /* dhcp server address that offered this lease (ip_addr_t because passed to UDP) */
213   u8_t subnet_mask_given;
214   ip4_addr_t offered_sn_mask;
215   ip4_addr_t offered_gw_addr;
216   ip4_addr_t relay_ip;
217   u32_t offered_t0_lease; /* lease period (in seconds) */
218   u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */
219   u32_t offered_t2_rebind; /* recommended rebind time (usually 87.5 of lease period)  */
220 
221   /* incoming msg */
222   struct dhcp_msg *msg_in;
223   struct pbuf *p_out; /* pbuf of outcoming msg */
224   struct dhcp_msg *msg_out; /* outgoing msg */
225   u16_t options_out_len; /* outgoing msg options length */
226 
227   u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
228   dhcp_num_t cli_cnt;
229   /* cli_idx = LWIP_DHCP_NATIVE_IDX always means the client for the netif */
230   dhcp_num_t cli_idx;
231   struct dhcp_state states[DHCP_CLIENT_NUM];
232 };
233 
234 struct dhcp {
235   /* track PCB allocation state */
236   u8_t pcb_allocated;
237 #if LWIP_DHCP_AUTOIP_COOP
238   u8_t autoip_coop_state;
239 #endif
240 
241 #if LWIP_DHCP_BOOTP_FILE
242   ip4_addr_t offered_si_addr;
243   char boot_file_name[DHCP_BOOT_FILE_LEN];
244 #endif /* LWIP_DHCP_BOOTPFILE */
245 #if LWIP_DHCP_SUBSTITUTE
246   u8_t flags;
247   struct dhcp_clients_info *clis_info;
248 #endif
249   struct dhcp_client client;
250 };
251 
252 #ifdef LWIP_DHCPS
253 struct dyn_lease_addr {
254   u8_t cli_hwaddr[DHCP_CHADDR_LEN];
255   u32_t flags;
256   u32_t leasetime;
257   u32_t proposed_leasetime;
258   ip4_addr_t cli_addr;
259 };
260 
261 struct dhcps {
262   struct udp_pcb *pcb;
263   struct dyn_lease_addr leasearr[LWIP_DHCPS_MAX_LEASE];
264   u8_t pcb_allocated;
265   u8_t lease_num;
266   struct netif *netif;
267   ip4_addr_t start_addr;
268   ip4_addr_t end_addr;
269 #if LWIP_DHCPS_AGENT_INFO
270   struct pbuf *p_in; /* pbuf of incoming msg */
271 #endif
272 };
273 #endif
274 
275 #if LWIP_API_RICH
276 void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp);
277 /* Remove a struct dhcp previously set to the netif using dhcp_set_struct() */
278 void dhcp_remove_struct(struct netif *netif);
279 #endif /* LWIP_API_RICH */
280 
281 void dhcp_cleanup(struct netif *netif);
282 err_t dhcp_is_bound(struct netif *netif);
283 err_t dhcp_start(struct netif *netif);
284 err_t dhcp_renew(struct netif *netif);
285 err_t dhcp_release(struct netif *netif);
286 void dhcp_stop(struct netif *netif);
287 void dhcp_inform(struct netif *netif);
288 void dhcp_network_changed(struct netif *netif);
289 #if DHCP_DOES_ARP_CHECK
290 void dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr);
291 #endif
292 #if LWIP_API_RICH
293 u8_t dhcp_supplied_address(const struct netif *netif);
294 #endif /* LWIP_API_RICH */
295 /* to be called every minute */
296 void dhcp_coarse_tmr(void);
297 /* to be called every half second */
298 void dhcp_fine_tmr(void);
299 
300 #if LWIP_LOWPOWER
301 u32_t dhcp_coarse_tmr_tick(void);
302 u32_t dhcp_fine_tmr_tick(void);
303 #endif
304 
305 #if LWIP_DHCP_GET_NTP_SRV
306 /* This function must exist, in other to add offered NTP servers to
307  * the NTP (or SNTP) engine.
308  * See LWIP_DHCP_MAX_NTP_SERVERS */
309 extern void dhcp_set_ntp_servers(u8_t num_ntp_servers, const ip4_addr_t *ntp_server_addrs);
310 #endif /* LWIP_DHCP_GET_NTP_SRV */
311 
312 #define netif_dhcp_data(netif) ((struct dhcp*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP))
313 
314 #if LWIP_DHCP_SUBSTITUTE
315 
316 struct dhcp_client_info {
317   ip4_addr_t ipaddr;
318   u8_t mac[NETIF_MAX_HWADDR_LEN];
319 #if NETIF_MAX_HWADDR_LEN != 6
320   u8_t mac_len;
321 #endif
322 };
323 
324 struct dhcp_clients_info {
325   dhcp_num_t num;
326   struct dhcp_client_info clis[0];
327 };
328 
329 #if LWIP_ARP
330 void dhcp_events_record(struct netif *netif, u8_t flags);
331 void dhcp_events_trigger(struct netif *netif);
332 #endif /* LWIP_ARP */
333 err_t dhcp_substitute_start(struct netif *netif, dhcp_num_t mac_idx);
334 void dhcp_substitute_stop(struct netif *netif, dhcp_num_t mac_idx);
335 err_t dhcp_substitute_idx_to_ip(struct netif *netif, dhcp_num_t idx, ip4_addr_t *ip);
336 err_t dhcp_clients_info_get(struct netif *netif, void *arg);
337 err_t dhcp_clients_info_free(struct netif *netif, void *arg);
338 #if LWIP_ENABLE_BASIC_SHELL_CMD
339 s32_t dhcp_netif_addr_clients_check(const struct netif *netif, const ip4_addr_t *ipaddr);
340 #endif /* LWIP_ENABLE_BASIC_SHELL_CMD */
341 #endif /* LWIP_DHCP_SUBSTITUTE */
342 
343 #if defined (__cplusplus) && __cplusplus
344 }
345 #endif
346 
347 #endif /* LWIP_DHCP */
348 
349 #endif /* LWIP_HDR_DHCP_H */
350