/* libdhcp/dhcp_common.h - Base definitions for the DHCP protocol * * Copyright (C) 2024 Luke T. Shumaker * SPDX-License-Identifier: AGPL-3.0-or-later * * ----------------------------------------------------------------------------- * https://github.com/Wiznet/ioLibrary_Driver/blob/b981401e7f3d07015619adf44c13998e13e777f9/Internet/DHCP/dhcp.c * * Copyright (c) 2013, WIZnet Co., LTD. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * * SPDX-License-Identifier: BSD-3-Clause * * ----------------------------------------------------------------------------- * https://github.com/Wiznet/ioLibrary_Driver/blob/b981401e7f3d07015619adf44c13998e13e777f9/license.txt * * Copyright (c) 2014 WIZnet Co.,Ltd. * Copyright (c) WIZnet ioLibrary Project. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * SPDX-License-Identifier: MIT */ #ifndef _LIBDHCP_DHCP_COMMON_H_ #define _LIBDHCP_DHCP_COMMON_H_ #include /* Config *********************************************************************/ #include "config.h" #ifndef CONFIG_DHCP_OPT_SIZE #error config.h must define CONFIG_DHCP_OPT_SIZE (minimum 312) #endif /* RFC 2131 definitions *******************************************************/ /** * "A DHCP client must be prepared to receive DHCP messages with an * 'options' field of at least length 312 octets." -- * https://datatracker.ietf.org/doc/html/rfc2131#page-9 */ #define DHCP_MSG_MIN_MAX_OPT_SIZE 312 static_assert(CONFIG_DHCP_OPT_SIZE >= DHCP_MSG_MIN_MAX_OPT_SIZE); /** https://datatracker.ietf.org/doc/html/rfc2131#page-9 */ struct dhcp_msg { uint8_t op; /* DHCP_OP_{x} */ uint8_t htype; /* DHCP_HTYPE_{x} */ uint8_t hlen; /* length of ->chaddr (`sizeof(struct net_eth_addr)`) */ uint8_t hops; uint32be_t xid; /* transaction ID */ uint16be_t secs; uint16be_t flags; /* DHCP_FLAG_{x} */ struct net_ip4_addr ciaddr; /* Request IP to DHCP sever */ struct net_ip4_addr yiaddr; /* Offered IP from DHCP server */ struct net_ip4_addr siaddr; /* next-server IP address */ struct net_ip4_addr giaddr; /* relay-agent IP address */ uint8_t chaddr[16]; /* client hardware (MAC) address */ uint8_t sname[64]; /* server name (not used) */ uint8_t file[128]; /* boot file name (not used) */ uint8_t options[CONFIG_DHCP_OPT_SIZE]; }; static_assert(offsetof(struct dhcp_msg, options) == 236); #define DHCP_MSG_BASE_SIZE offsetof(struct dhcp_msg, options) /** https://datatracker.ietf.org/doc/html/rfc2131#page-10 */ #define DHCP_OP_BOOTREQUEST 1 #define DHCP_OP_BOOTREPLY 2 /** https://datatracker.ietf.org/doc/html/rfc2131#page-11 */ #define DHCP_FLAG_BROADCAST 0x8000 /* The BROADCAST flag (set by the client) * indicates that the server should use * broadcast-IP replies instead of * unicast-IP because the client is not * yet capable of receiving unicast-IP at * this stage of configuration. */ /** https://datatracker.ietf.org/doc/html/rfc2131#section-3 */ static const uint8_t dhcp_magic_cookie[] = {99, 130, 83, 99}; /** https://datatracker.ietf.org/doc/html/rfc2131#section-3.3 */ #define DHCP_INFINITY 0xffffffff /* IANA assignments ***********************************************************/ /** * Port Numbers * https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml */ #define DHCP_PORT_SERVER ((uint16_t)67) #define DHCP_PORT_CLIENT ((uint16_t)68) /** * Hardware Types * https://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml#arp-parameters-2 */ #define DHCP_HTYPE_ETHERNET ((uint8_t) 1) /** * DHCP Options * https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml#options */ #define DHCP_OPT_PAD ((uint8_t) 0) /* RFC2132: length: 0; meaning: None */ #define DHCP_OPT_SUBNET_MASK ((uint8_t) 1) /* RFC2132: length: 4; meaning: Subnet Mask Value */ #define DHCP_OPT_TIME_OFFSET ((uint8_t) 2) /* RFC2132: length: 4; meaning: Time Offset in Seconds from UTC (note: deprecated by 100 and 101 */ #define DHCP_OPT_ROUTER ((uint8_t) 3) /* RFC2132: length: N; meaning: N/4 Router addresses */ #define DHCP_OPT_TIME_SERVER ((uint8_t) 4) /* RFC2132: length: N; meaning: N/4 Timeserver addresses */ #define DHCP_OPT_NAME_SERVER ((uint8_t) 5) /* RFC2132: length: N; meaning: N/4 IEN-116 Server addresses */ #define DHCP_OPT_DOMAIN_SERVER ((uint8_t) 6) /* RFC2132: length: N; meaning: N/4 DNS Server addresses */ #define DHCP_OPT_LOG_SERVER ((uint8_t) 7) /* RFC2132: length: N; meaning: N/4 Logging Server addresses */ #define DHCP_OPT_QUOTES_SERVER ((uint8_t) 8) /* RFC2132: length: N; meaning: N/4 Quotes Server addresses */ #define DHCP_OPT_LPR_SERVER ((uint8_t) 9) /* RFC2132: length: N; meaning: N/4 Printer Server addresses */ #define DHCP_OPT_IMPRESS_SERVER ((uint8_t) 10) /* RFC2132: length: N; meaning: N/4 Impress Server addresses */ #define DHCP_OPT_RLP_SERVER ((uint8_t) 11) /* RFC2132: length: N; meaning: N/4 RLP Server addresses */ #define DHCP_OPT_HOSTNAME ((uint8_t) 12) /* RFC2132: length: N; meaning: Hostname string */ #define DHCP_OPT_BOOT_FILE_SIZE ((uint8_t) 13) /* RFC2132: length: 2; meaning: Size of boot file in 512 byte chunks */ #define DHCP_OPT_MERIT_DUMP_FILE ((uint8_t) 14) /* RFC2132: length: N; meaning: Client to dump and name the file to dump it to */ #define DHCP_OPT_DOMAIN_NAME ((uint8_t) 15) /* RFC2132: length: N; meaning: The DNS domain name of the client */ #define DHCP_OPT_SWAP_SERVER ((uint8_t) 16) /* RFC2132: length: N; meaning: Swap Server address */ #define DHCP_OPT_ROOT_PATH ((uint8_t) 17) /* RFC2132: length: N; meaning: Path name for root disk */ #define DHCP_OPT_EXTENSION_FILE ((uint8_t) 18) /* RFC2132: length: N; meaning: Path name for more BOOTP info */ #define DHCP_OPT_FORWARD_ONOFF ((uint8_t) 19) /* RFC2132: length: 1; meaning: Enable/Disable IP Forwarding */ #define DHCP_OPT_SRCRTE_ONOFF ((uint8_t) 20) /* RFC2132: length: 1; meaning: Enable/Disable Source Routing */ #define DHCP_OPT_POLICY_FILTER ((uint8_t) 21) /* RFC2132: length: N; meaning: Routing Policy Filters */ #define DHCP_OPT_MAX_DG_ASSEMBLY ((uint8_t) 22) /* RFC2132: length: 2; meaning: Max Datagram Reassembly Size */ #define DHCP_OPT_DEFAULT_IP_TTL ((uint8_t) 23) /* RFC2132: length: 1; meaning: Default IP Time to Live */ #define DHCP_OPT_MTU_TIMEOUT ((uint8_t) 24) /* RFC2132: length: 4; meaning: Path MTU Aging Timeout */ #define DHCP_OPT_MTU_PLATEAU ((uint8_t) 25) /* RFC2132: length: N; meaning: Path MTU Plateau Table */ #define DHCP_OPT_MTU_INTERFACE ((uint8_t) 26) /* RFC2132: length: 2; meaning: Interface MTU Size */ #define DHCP_OPT_MTU_SUBNET ((uint8_t) 27) /* RFC2132: length: 1; meaning: All Subnets are Local */ #define DHCP_OPT_BROADCAST_ADDRESS ((uint8_t) 28) /* RFC2132: length: 4; meaning: Broadcast Address */ #define DHCP_OPT_MASK_DISCOVERY ((uint8_t) 29) /* RFC2132: length: 1; meaning: Perform Mask Discovery */ #define DHCP_OPT_MASK_SUPPLIER ((uint8_t) 30) /* RFC2132: length: 1; meaning: Provide Mask to Others */ #define DHCP_OPT_ROUTER_DISCOVERY ((uint8_t) 31) /* RFC2132: length: 1; meaning: Perform Router Discovery */ #define DHCP_OPT_ROUTER_REQUEST ((uint8_t) 32) /* RFC2132: length: 4; meaning: Router Solicitation Address */ #define DHCP_OPT_STATIC_ROUTE ((uint8_t) 33) /* RFC2132: length: N; meaning: Static Routing Table */ #define DHCP_OPT_TRAILERS ((uint8_t) 34) /* RFC2132: length: 1; meaning: Trailer Encapsulation */ #define DHCP_OPT_ARP_TIMEOUT ((uint8_t) 35) /* RFC2132: length: 4; meaning: ARP Cache Timeout */ #define DHCP_OPT_ETHERNET ((uint8_t) 36) /* RFC2132: length: 1; meaning: Ethernet Encapsulation */ #define DHCP_OPT_DEFAULT_TCP_TTL ((uint8_t) 37) /* RFC2132: length: 1; meaning: Default TCP Time to Live */ #define DHCP_OPT_KEEPALIVE_TIME ((uint8_t) 38) /* RFC2132: length: 4; meaning: TCP Keepalive Interval */ #define DHCP_OPT_KEEPALIVE_DATA ((uint8_t) 39) /* RFC2132: length: 1; meaning: TCP Keepalive Garbage */ #define DHCP_OPT_NIS_DOMAIN ((uint8_t) 40) /* RFC2132: length: N; meaning: NIS Domain Name */ #define DHCP_OPT_NIS_SERVERS ((uint8_t) 41) /* RFC2132: length: N; meaning: NIS Server Addresses */ #define DHCP_OPT_NTP_SERVERS ((uint8_t) 42) /* RFC2132: length: N; meaning: NTP Server Addresses */ #define DHCP_OPT_VENDOR_SPECIFIC ((uint8_t) 43) /* RFC2132: length: N; meaning: Vendor Specific Information */ #define DHCP_OPT_NETBIOS_NAME_SRV ((uint8_t) 44) /* RFC2132: length: N; meaning: NETBIOS Name Servers */ #define DHCP_OPT_NETBIOS_DIST_SRV ((uint8_t) 45) /* RFC2132: length: N; meaning: NETBIOS Datagram Distribution */ #define DHCP_OPT_NETBIOS_NODE_TYPE ((uint8_t) 46) /* RFC2132: length: 1; meaning: NETBIOS Node Type */ #define DHCP_OPT_NETBIOS_SCOPE ((uint8_t) 47) /* RFC2132: length: N; meaning: NETBIOS Scope */ #define DHCP_OPT_X_WINDOW_FONT ((uint8_t) 48) /* RFC2132: length: N; meaning: X Window Font Server */ #define DHCP_OPT_X_WINDOW_MANAGER ((uint8_t) 49) /* RFC2132: length: N; meaning: X Window Display Manager */ #define DHCP_OPT_ADDRESS_REQUEST ((uint8_t) 50) /* RFC2132: length: 4; meaning: Requested IP Address */ #define DHCP_OPT_ADDRESS_TIME ((uint8_t) 51) /* RFC2132: length: 4; meaning: IP Address Lease Time */ #define DHCP_OPT_OVERLOAD ((uint8_t) 52) /* RFC2132: length: 1; meaning: Overload "sname" or "file */ #define DHCP_OPT_DHCP_MSG_TYPE ((uint8_t) 53) /* RFC2132: length: 1; meaning: DHCP Message Type */ #define DHCP_OPT_DHCP_SERVER_ID ((uint8_t) 54) /* RFC2132: length: 4; meaning: DHCP Server Identification */ #define DHCP_OPT_PARAMETER_LIST ((uint8_t) 55) /* RFC2132: length: N; meaning: Parameter Request List */ #define DHCP_OPT_DHCP_MESSAGE ((uint8_t) 56) /* RFC2132: length: N; meaning: DHCP Error Message */ #define DHCP_OPT_DHCP_MAX_MSG_SIZE ((uint8_t) 57) /* RFC2132: length: 2; meaning: DHCP Maximum Message Size */ /* note: includes IP & UDP headers (20 and 8, respectively) */ #define DHCP_OPT_RENEWAL_TIME ((uint8_t) 58) /* RFC2132: length: 4; meaning: DHCP Renewal (T1) Time */ #define DHCP_OPT_REBINDING_TIME ((uint8_t) 59) /* RFC2132: length: 4; meaning: DHCP Rebinding (T2) Time */ #define DHCP_OPT_CLASS_ID ((uint8_t) 60) /* RFC2132: length: N; meaning: Class Identifier */ #define DHCP_OPT_CLIENT_ID ((uint8_t) 61) /* RFC2132: length: N; meaning: Client Identifier */ /* ... */ #define DHCP_OPT_END ((uint8_t)255) /* RFC2132: length: 0; meaning: None */ static inline bool dhcp_opt_length_is_valid(uint8_t opt, uint16_t len) { switch (opt) { /* RFC 2132 */ case DHCP_OPT_PAD: return len == 0; case DHCP_OPT_SUBNET_MASK: return len == 4; case DHCP_OPT_TIME_OFFSET: return len == 4; case DHCP_OPT_ROUTER: return len >= 4 && len % 4 == 0; case DHCP_OPT_TIME_SERVER: return len >= 4 && len % 4 == 0; case DHCP_OPT_NAME_SERVER: return len >= 4 && len % 4 == 0; case DHCP_OPT_DOMAIN_SERVER: return len >= 4 && len % 4 == 0; case DHCP_OPT_LOG_SERVER: return len >= 4 && len % 4 == 0; case DHCP_OPT_QUOTES_SERVER: return len >= 4 && len % 4 == 0; case DHCP_OPT_LPR_SERVER: return len >= 4 && len % 4 == 0; case DHCP_OPT_IMPRESS_SERVER: return len >= 4 && len % 4 == 0; case DHCP_OPT_RLP_SERVER: return len >= 4 && len % 4 == 0; case DHCP_OPT_HOSTNAME: return len >= 1; case DHCP_OPT_BOOT_FILE_SIZE: return len == 2; case DHCP_OPT_MERIT_DUMP_FILE: return len >= 1; case DHCP_OPT_DOMAIN_NAME: return len >= 1; case DHCP_OPT_SWAP_SERVER: return len == 4; /* IANA says length is "N", but RFC 2132 says "length is 4"; likely releated to errata ID 487 */ case DHCP_OPT_ROOT_PATH: return len >= 1; case DHCP_OPT_EXTENSION_FILE: return len >= 1; case DHCP_OPT_FORWARD_ONOFF: return len == 1; case DHCP_OPT_SRCRTE_ONOFF: return len == 1; case DHCP_OPT_POLICY_FILTER: return len >= 8 && len % 8 == 0; case DHCP_OPT_MAX_DG_ASSEMBLY: return len == 2; case DHCP_OPT_DEFAULT_IP_TTL: return len == 1; case DHCP_OPT_MTU_TIMEOUT: return len == 4; case DHCP_OPT_MTU_PLATEAU: return len >= 2 && len % 2 == 0; case DHCP_OPT_MTU_INTERFACE: return len == 2; case DHCP_OPT_MTU_SUBNET: return len == 1; case DHCP_OPT_BROADCAST_ADDRESS: return len == 4; case DHCP_OPT_MASK_DISCOVERY: return len == 1; case DHCP_OPT_MASK_SUPPLIER: return len == 1; case DHCP_OPT_ROUTER_DISCOVERY: return len == 1; case DHCP_OPT_ROUTER_REQUEST: return len == 4; case DHCP_OPT_STATIC_ROUTE: return len >= 8 && len % 8 == 0; case DHCP_OPT_TRAILERS: return len == 1; case DHCP_OPT_ARP_TIMEOUT: return len == 4; case DHCP_OPT_ETHERNET: return len == 1; case DHCP_OPT_DEFAULT_TCP_TTL: return len == 1; case DHCP_OPT_KEEPALIVE_TIME: return len == 4; case DHCP_OPT_KEEPALIVE_DATA: return len == 1; case DHCP_OPT_NIS_DOMAIN: return len >= 1; case DHCP_OPT_NIS_SERVERS: return len >= 4 && len % 4 == 0; case DHCP_OPT_NTP_SERVERS: return len >= 4 && len % 4 == 0; case DHCP_OPT_VENDOR_SPECIFIC: return len >= 1; case DHCP_OPT_NETBIOS_NAME_SRV: return len >= 4 && len % 4 == 0; case DHCP_OPT_NETBIOS_DIST_SRV: return len >= 4 && len % 4 == 0; case DHCP_OPT_NETBIOS_NODE_TYPE: return len == 1; case DHCP_OPT_NETBIOS_SCOPE: return len >= 1; case DHCP_OPT_X_WINDOW_FONT: return len >= 4 && len % 4 == 0; case DHCP_OPT_X_WINDOW_MANAGER: return len >= 4 && len % 4 == 0; case DHCP_OPT_ADDRESS_REQUEST: return len == 4; case DHCP_OPT_ADDRESS_TIME: return len == 4; case DHCP_OPT_OVERLOAD: return len == 1; case DHCP_OPT_DHCP_MSG_TYPE: return len == 1; case DHCP_OPT_DHCP_SERVER_ID: return len == 4; case DHCP_OPT_PARAMETER_LIST: return len >= 1; case DHCP_OPT_DHCP_MESSAGE: return len >= 1; case DHCP_OPT_DHCP_MAX_MSG_SIZE: return len == 2; case DHCP_OPT_RENEWAL_TIME: return len == 4; case DHCP_OPT_REBINDING_TIME: return len == 4; case DHCP_OPT_CLASS_ID: return len >= 1; case DHCP_OPT_CLIENT_ID: return len >= 2; /* RFC 2132 */ case DHCP_OPT_END: return len == 0; /* Unrecognized */ default: return true; } }; /** * DHCP Message Type 53 Values * https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml#message-type-53 */ #define DHCP_MSGTYP_DISCOVER ((uint8_t) 1) /* RFC2132, client->server */ #define DHCP_MSGTYP_OFFER ((uint8_t) 2) /* RFC2132, server->client */ #define DHCP_MSGTYP_REQUEST ((uint8_t) 3) /* RFC2132, client->server */ #define DHCP_MSGTYP_DECLINE ((uint8_t) 4) /* RFC2132, client->server */ #define DHCP_MSGTYP_ACK ((uint8_t) 5) /* RFC2132, server->client */ #define DHCP_MSGTYP_NAK ((uint8_t) 6) /* RFC2132, server->client */ #define DHCP_MSGTYP_RELEASE ((uint8_t) 7) /* RFC2132, client->server */ #define DHCP_MSGTYP_INFORM ((uint8_t) 8) /* RFC2132, client->server */ #endif /* _LIBDHCP_DHCP_COMMON_H_ */