#include #include #include #include #include #include #include #include #include "ip4.h" #include "udp4.h" #include "dhcp4.h" #include "eth.h" #include "packet.h" #include "interface.h" #include "sock.h" int main() { int sock = sock::create(67); char const * interface_name = "enp175s0"; int ifa_index = sock::interface_index(sock, interface_name); sock::bind_interface(sock, ifa_index); uint8_t eth_source_address[6]; sock::interface_address(sock, interface_name, eth_source_address); packet::packet p{}; dhcp4::options options{}; static uint8_t recvbuf[65536]; static uint8_t sendbuf[16384]; uint32_t ip4_client_address = ip4::fromstr("10.0.0.50"); uint32_t ip4_server_address = ip4::fromstr("10.0.0.5"); uint32_t ip4_subnet_mask = ip4::fromstr("255.255.255.0"); uint32_t ip4_router = ip4::fromstr("10.0.0.5"); uint32_t ip4_domain_name_server = ip4::fromstr("8.8.8.8"); while (true) { ////////////////////////////////////////////////////////////////////// // dhcp recv ////////////////////////////////////////////////////////////////////// { struct sockaddr_ll recv_address; int flags = 0; socklen_t socklen = (sizeof (struct sockaddr_ll)); ssize_t rret = recvfrom(sock, recvbuf, (sizeof (recvbuf)), flags, (struct sockaddr *)&recv_address, &socklen); if (rret < 0) { perror("recvfrom"); exit(EXIT_FAILURE); } packet::parse(recvbuf, rret, &p); int dhcp4_options_length = rret - (packet::dhcp4_offset + (offsetof (dhcp4::message, options))); dhcp4::parse_options(p.dhcp4, dhcp4_options_length, &options); printf("dhcp4 op: %d\n", p.dhcp4->op); printf("message type: %s\n", dhcp4::message_type_tostr(options.message_type)); printf("transaction id: %08x\n", ntohl(p.dhcp4->xid)); } if (options.message_type == dhcp4::message_type::dhcpdiscover) { dhcp4::message_parameters params = { .your_ip_address = ip4_client_address, .next_server_ip_address = ip4_server_address, .server_identifier = ip4_server_address, .subnet_mask = ip4_subnet_mask, .router = ip4_router, .domain_name_server = ip4_domain_name_server, }; uint8_t const * eth_destination_address = p.eth->source_address; uint32_t ip4_source_address = ip4_server_address; uint32_t ip4_destination_address = ip4_client_address; uint32_t dhcp_transaction_id = ntohl(p.dhcp4->xid); int length = packet::make(sendbuf, dhcp4::op::bootreply, eth_source_address, eth_destination_address, eth_destination_address, // eth_client_address ip4_source_address, ip4_destination_address, 67, 68, dhcp_transaction_id, dhcp4::message_type::dhcpoffer, ¶ms); sock::send(sock, ifa_index, sendbuf, length, eth_destination_address); } if (options.message_type == dhcp4::message_type::dhcprequest) { printf("requested ip address: %s\n", ip4::tostr(options.requested_ip_address)); if (options.requested_ip_address != ip4_client_address) { printf("should NAK\n"); continue; } dhcp4::message_parameters params = { .your_ip_address = ip4_client_address, .next_server_ip_address = ip4_server_address, .server_identifier = ip4_server_address, .subnet_mask = ip4_subnet_mask, .router = ip4_router, .domain_name_server = ip4_domain_name_server, }; uint8_t const * eth_destination_address = p.eth->source_address; uint32_t ip4_source_address = ip4_server_address; uint32_t ip4_destination_address = ip4_client_address; uint32_t dhcp_transaction_id = ntohl(p.dhcp4->xid); int length = packet::make(sendbuf, dhcp4::op::bootreply, eth_source_address, eth_destination_address, eth_destination_address, // eth_client_address ip4_source_address, ip4_destination_address, 67, 68, dhcp_transaction_id, dhcp4::message_type::dhcpack, ¶ms); sock::send(sock, ifa_index, sendbuf, length, eth_destination_address); } } }