summaryrefslogtreecommitdiff
path: root/libdhcp/dhcp_common.h
diff options
context:
space:
mode:
Diffstat (limited to 'libdhcp/dhcp_common.h')
-rw-r--r--libdhcp/dhcp_common.h134
1 files changed, 116 insertions, 18 deletions
diff --git a/libdhcp/dhcp_common.h b/libdhcp/dhcp_common.h
index 2bde7a4..0be3a27 100644
--- a/libdhcp/dhcp_common.h
+++ b/libdhcp/dhcp_common.h
@@ -1,4 +1,4 @@
-/* libdhcp/dhcp_common.c - TODO
+/* libdhcp/dhcp_common.h - Base definitions for the DHCP protocol
*
* Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -64,14 +64,29 @@
* SPDX-License-Identifier: MIT
*/
+#ifndef _LIBDHCP_DHCP_COMMON_H_
+#define _LIBDHCP_DHCP_COMMON_H_
+
+#include <libmisc/endian.h>
+
/* Config *********************************************************************/
+#include "config.h"
+
#ifndef CONFIG_DHCP_OPT_SIZE
- #define CONFIG_DHCP_OPT_SIZE 312
+ #define CONFIG_DHCP_OPT_SIZE DHCP_MSG_MIN_MAX_OPT_SIZE
#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} */
@@ -86,8 +101,8 @@ struct dhcp_msg {
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 (not used) */
- struct net_ip4_addr giaddr; /* relay-agent IP address (not used) */
+ 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) */
@@ -95,20 +110,25 @@ struct dhcp_msg {
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)
+#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
+#define DHCP_OP_BOOTREQUEST 1
+#define DHCP_OP_BOOTREPLY 2
/** https://datatracker.ietf.org/doc/html/rfc2131#page-11 */
-#define DHCP_FLAG_BROADCAST 0x8000
+#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
+#define DHCP_INFINITY 0xffffffff
/* IANA assignments ***********************************************************/
@@ -186,22 +206,100 @@ static const uint8_t dhcp_magic_cookie[] = {99, 130, 83, 99};
#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 */
+#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 */
-#define DHCP_MSGTYP_OFFER ((uint8_t) 2) /* RFC2132 */
-#define DHCP_MSGTYP_REQUEST ((uint8_t) 3) /* RFC2132 */
-#define DHCP_MSGTYP_DECLINE ((uint8_t) 4) /* RFC2132 */
-#define DHCP_MSGTYP_ACK ((uint8_t) 5) /* RFC2132 */
-#define DHCP_MSGTYP_NAK ((uint8_t) 6) /* RFC2132 */
-#define DHCP_MSGTYP_RELEASE ((uint8_t) 7) /* RFC2132 */
-#define DHCP_MSGTYP_INFORM ((uint8_t) 8) /* RFC2132 */
+#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_ */