114 lines
2.8 KiB
C
114 lines
2.8 KiB
C
//
|
|
// Created by epagris on 2022.12.09..
|
|
//
|
|
|
|
#include <stdlib.h>
|
|
#include "dhcp.h"
|
|
#include "../../dynmem.h"
|
|
#include "../../utils.h"
|
|
#include "../../connection_block.h"
|
|
#include "../conn_blocks/udp_connblock.h"
|
|
|
|
static struct {
|
|
DhcpState state;
|
|
void * buf;
|
|
ConnBlock connb;
|
|
uint32_t tranId;
|
|
} s;
|
|
|
|
static const uint8_t DHCP_MAGIC_COOKIE[] = { 99, 130, 83, 99 };
|
|
|
|
#define SNAME_LEN (64)
|
|
#define FILE_LEN (128)
|
|
|
|
// (Exact copy of the standard.)
|
|
typedef enum {
|
|
DHCPDISCOVER = 1,
|
|
DHCPOFFER = 2,
|
|
DHCPREQUEST = 3,
|
|
DHCPDECLINE = 4,
|
|
DHCPACK = 5,
|
|
DHCPNAK = 6,
|
|
DHCPRELEASE = 7
|
|
} DhcpMsgType;
|
|
|
|
static void dhcp_option_insert_msg_type(uint8_t ** bufPtr, int msgType) {
|
|
(*bufPtr)[0] = 0x35;
|
|
(*bufPtr)[1] = 1;
|
|
(*bufPtr)[2] = msgType;
|
|
(*bufPtr) += 3;
|
|
}
|
|
|
|
static void dhcp_option_insert_max_msg_size(uint8_t ** bufPtr, uint16_t maxSize) {
|
|
(*bufPtr)[0] = 0x39;
|
|
(*bufPtr)[1] = 2;
|
|
(*bufPtr)[2] = (maxSize >> 8) & 0xFF;
|
|
(*bufPtr)[3] = maxSize & 0xFF;
|
|
(*bufPtr) += 4;
|
|
}
|
|
|
|
static void dhcp_option_insert_end(uint8_t ** bufPtr) {
|
|
(*bufPtr)[0] = 0xFF;
|
|
(*bufPtr) += 1;
|
|
}
|
|
|
|
static void dhcp_send(EthInterface * intf, DhcpOps * ops) {
|
|
// construct message
|
|
uint8_t * buf = (uint8_t *)s.buf;
|
|
memset(buf, 0, DHCP_MIN_PACKET_SIZE);
|
|
FILL_BYTE_ADVANCE(buf, &(ops->op));
|
|
FILL_BYTE_ADVANCE(buf, &(ops->htype));
|
|
FILL_BYTE_ADVANCE(buf, &(ops->hlen));
|
|
FILL_BYTE_ADVANCE(buf, &(ops->hops));
|
|
FILL_DWORD_H2N_ADVANCE(buf, ops->xid);
|
|
FILL_WORD_H2N_ADVANCE(buf, ops->secs);
|
|
FILL_WORD_H2N_ADVANCE(buf, ops->flags);
|
|
FILL_DWORD_H2N_ADVANCE(buf, ops->ciaddr);
|
|
FILL_DWORD_H2N_ADVANCE(buf, ops->yiaddr);
|
|
FILL_DWORD_H2N_ADVANCE(buf, ops->siaddr);
|
|
FILL_DWORD_H2N_ADVANCE(buf, ops->giaddr);
|
|
FILL_ADVANCE(buf, ops->chaddr, 16);
|
|
buf += SNAME_LEN + FILE_LEN;
|
|
FILL_ADVANCE(buf, DHCP_MAGIC_COOKIE, 4); // DHCP magic cookie
|
|
|
|
// insert options
|
|
dhcp_option_insert_msg_type(&buf, DHCPDISCOVER);
|
|
dhcp_option_insert_max_msg_size(&buf, 1500);
|
|
dhcp_option_insert_end(&buf);
|
|
|
|
udp_sendto(&s.connb, s.buf, DHCP_MIN_PACKET_SIZE, IPv4_ANY_ADDR, DHCP_SERVER_PORT);
|
|
}
|
|
|
|
static void dhcp_discover(EthInterface * intf) {
|
|
s.tranId = rand();
|
|
DhcpOps ops = { 0 };
|
|
|
|
ops.op = DHCP_BOOTREQUEST;
|
|
ops.htype = 1;
|
|
ops.hlen = 6;
|
|
ops.hops = 0;
|
|
ops.xid = s.tranId;
|
|
ops.secs = 0;
|
|
ops.flags = 0;
|
|
ops.ciaddr = 0;
|
|
ops.yiaddr = 0;
|
|
ops.siaddr = 0;
|
|
ops.giaddr = 0;
|
|
|
|
memcpy(ops.chaddr, intf->mac, ETH_HW_ADDR_LEN);
|
|
|
|
dhcp_send(intf, &ops);
|
|
}
|
|
|
|
static int dhcp_resp_cb(const Pckt * pckt) {
|
|
return 0;
|
|
}
|
|
|
|
void dhcp_initiate(EthInterface *intf) {
|
|
s.state = DHCP_INIT_REBOOT;
|
|
s.buf = dynmem_alloc(DHCP_MIN_PACKET_SIZE);
|
|
s.connb = udp_new_connblock(intf, IPv4_ANY_ADDR, DHCP_CLIENT_PORT, dhcp_resp_cb);
|
|
|
|
dhcp_discover(intf);
|
|
}
|