// // Created by epagris on 2022.12.09.. // #include #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); }