From f9928a1a08c57fe853888119a996c3acc98ee09d Mon Sep 17 00:00:00 2001 From: Johannes Stoelp Date: Fri, 14 Jan 2022 23:51:05 +0100 Subject: Initial version of nodemcuv2 dhcp server Able to offer IP address + DNS/Gateway ... Worked with devices at my hand. --- lib/dhcp/dhcp.h | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 lib/dhcp/dhcp.h (limited to 'lib/dhcp/dhcp.h') diff --git a/lib/dhcp/dhcp.h b/lib/dhcp/dhcp.h new file mode 100644 index 0000000..ce904f0 --- /dev/null +++ b/lib/dhcp/dhcp.h @@ -0,0 +1,116 @@ +// Copyright (c) 2022 Johannes Stoelp +// +// dhcp protocol: https://datatracker.ietf.org/doc/html/rfc2131 +// dhcp options : https://datatracker.ietf.org/doc/html/rfc2132 + +#ifndef DHCP_H +#define DHCP_H + +#include "types.h" + +#include + +// -- Global constants. + +constexpr u16 DHCP_SERVER_PORT = 67; +constexpr u16 DHCP_CLIENT_PORT = 68; + +constexpr usize DHCP_MESSAGE_LEN = 576; +constexpr usize DHCP_MESSAGE_MIN_LEN = 243; + +constexpr u32 DHCP_OPTION_COOKIE = 0x63538263; + +enum class dhcp_operation : u8 { + BOOTREQUEST = 1, + BOOTREPLY, +}; + +enum class dhcp_option : u8 { + PAD = 0, + END = 255, + + // Vendor Extensions. + SUBNET_MASK = 1, + ROUTER = 3, + DNS = 6, + + // IP Layer Parameters per Interface. + BROADCAST_ADDR = 28, + + // DHCP Extensions. + REQUESTED_IP = 50, + IP_ADDRESS_LEASE_TIME, + OPTION_OVERLOAD, + DHCP_MESSAGE_TYPE, + SERVER_IDENTIFIER, + PARAMETER_REQUEST_LIST, + MESSAGE, + MAX_DHCP_MESSAGE_SIZE, + RENEWAL_TIME_T1, + REBINDING_TIME_T2, + CLASS_ID, + CLIENT_ID, +}; + +// -- DHCP message. + +enum class dhcp_message_type : u8 { + DHCP_DISCOVER = 1, + DHCP_OFFER, + DHCP_REQUEST, + DHCP_DECLINE, + DHCP_ACK, + DHCP_NAK, + DHCP_RELEAE, +}; + +struct dhcp_message { + dhcp_operation op; + u8 htype; + u8 hlen; + u8 hops; + u32 xid; + u16 secs; + u16 flags; + u32 ciaddr; + u32 yiaddr; + u32 siaddr; + u32 giaddr; + u8 chaddr[16]; + u8 sname[64]; + u8 file[128]; + u32 cookie; + u8 options[312 - 4 /* cookie len */]; +} __attribute__((packed)); + +static_assert(DHCP_MESSAGE_MIN_LEN == offsetof(dhcp_message, options) + 3 /* DHCP_MESSAGE_TYPE size */, + "Declare min size as dhcp_message with the DHCP_MESSAGE_TYPE option."); + +// -- DHCP Utilities. + +struct option_view { + const u8* data; + usize len; +}; + +// Search for the option with tag 'search_tag' in the options 'opt' of length 'len'. +std::optional get_option(const u8* opt, usize len, dhcp_option search_tag); + +template +constexpr T get_opt_val(const u8* opt_data) { + T ret = 0; + for (size_t i = 0; i < sizeof(T); ++i) { + ret = (ret << 8) | *opt_data++; + } + return ret; +} + +template +u8* put_opt_val(u8* opt_data, T val) { + for (size_t i = sizeof(T); i; --i) { + *opt_data++ = (val >> ((i - 1) * 8)) & 0xff; + } + return opt_data; +} + +#endif -- cgit v1.2.3