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