#include #include #include #include "dhcp4.h" namespace dhcp4 { int make_message(void * buf, uint32_t bootp_message_type, uint32_t transaction_id, uint8_t const * chaddr, uint32_t dhcp_message_type) { memset(buf, 0, (sizeof (message))); message * msg = reinterpret_cast(buf); msg->op = bootp_message_type; msg->htype = htype::ethernet; msg->hlen = 6; msg->xid = htonl(transaction_id); memcpy(msg->chaddr, chaddr, 6); int index = 0; uint8_t * cookie = &msg->options[index]; index += 4; cookie[0] = 0x63; cookie[1] = 0x82; cookie[2] = 0x53; cookie[3] = 0x63; uint8_t * message_type = &msg->options[index]; index += 2 + 1; message_type[0] = option::message_type; message_type[1] = 1; // length message_type[2] = dhcp_message_type; { uint8_t * prl = &msg->options[index]; int length = 3; index += 2 + length; prl[0] = option::parameter_request_list; prl[1] = length; prl[2] = option::subnet_mask; prl[3] = option::router; prl[4] = option::domain_name_server; } uint8_t * end = &msg->options[index]; index += 1; end[0] = 255; return (sizeof (message)) + index; } char const * message_type_tostr(int message_type) { switch (message_type) { case message_type::dhcpdiscover: return "dhcpdiscover"; case message_type::dhcpoffer: return "dhcpoffer"; case message_type::dhcprequest: return "dhcprequest"; case message_type::dhcpdecline: return "dhcpdecline"; case message_type::dhcpack: return "dhcpack"; case message_type::dhcpnak: return "dhcpnak"; case message_type::dhcprelease: return "dhcprelease"; case message_type::dhcpinform: return "dhcpinform"; default: assert(false); return nullptr; } } void parse_options(message const * m, int options_length, options * o) { uint8_t const * options = m->options; int index = 4; while (index + 2 <= options_length) { int option = options[index + 0]; int option_length = options[index + 1]; //printf("option %d length %d\n", option, option_length); switch (option) { case option::message_type: o->message_type = options[index + 2]; break; case option::subnet_mask: o->subnet_mask = *reinterpret_cast(&options[index + 2]); break; case option::router: o->router = *reinterpret_cast(&options[index + 2]); break; case option::domain_name_server: o->domain_name_server = *reinterpret_cast(&options[index + 2]); break; default: break; } index += 2 + option_length; } assert(options[index] == 255); } }