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