diff options
Diffstat (limited to 'libdhcp/dhcp_common.h')
-rw-r--r-- | libdhcp/dhcp_common.h | 134 |
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_ */ |