aboutsummaryrefslogblamecommitdiff
path: root/lib/dhcp/dhcp.h
blob: ce904f044ae37f61804dd6e837e77f89631d79d3 (plain) (tree)



















































































































                                                                                                       
// 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 <optional>

// -- 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<struct option_view> get_option(const u8* opt, usize len, dhcp_option search_tag);

template<typename T>
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<typename T>
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