Userspace: Implement super simple DHCP client
This commit is contained in:
		
							parent
							
								
									102aa50a41
								
							
						
					
					
						commit
						2138eeb87f
					
				| 
						 | 
					@ -8,6 +8,7 @@ set(USERSPACE_PROJECTS
 | 
				
			||||||
	chmod
 | 
						chmod
 | 
				
			||||||
	cp
 | 
						cp
 | 
				
			||||||
	dd
 | 
						dd
 | 
				
			||||||
 | 
						dhcp-client
 | 
				
			||||||
	echo
 | 
						echo
 | 
				
			||||||
	id
 | 
						id
 | 
				
			||||||
	init
 | 
						init
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					cmake_minimum_required(VERSION 3.26)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					project(dhcp-client CXX)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(SOURCES
 | 
				
			||||||
 | 
						main.cpp
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_executable(dhcp-client ${SOURCES})
 | 
				
			||||||
 | 
					target_compile_options(dhcp-client PUBLIC -O2 -g)
 | 
				
			||||||
 | 
					target_link_libraries(dhcp-client PUBLIC libc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_custom_target(dhcp-client-install
 | 
				
			||||||
 | 
						COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/dhcp-client ${BANAN_BIN}/
 | 
				
			||||||
 | 
						DEPENDS dhcp-client
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,380 @@
 | 
				
			||||||
 | 
					#include <BAN/Endianness.h>
 | 
				
			||||||
 | 
					#include <BAN/IPv4.h>
 | 
				
			||||||
 | 
					#include <BAN/MAC.h>
 | 
				
			||||||
 | 
					#include <BAN/Vector.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <net/if.h>
 | 
				
			||||||
 | 
					#include <netinet/in.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <stropts.h>
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DEBUG_DHCP 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct DHCPPacket
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint8_t							op;
 | 
				
			||||||
 | 
						uint8_t							htype	{ 0x01 };
 | 
				
			||||||
 | 
						uint8_t							hlen	{ 0x06 };
 | 
				
			||||||
 | 
						uint8_t							hops	{ 0x00 };
 | 
				
			||||||
 | 
						BAN::NetworkEndian<uint32_t>	xid		{ 0x3903F326 };
 | 
				
			||||||
 | 
						BAN::NetworkEndian<uint16_t>	secs	{ 0x0000 };
 | 
				
			||||||
 | 
						BAN::NetworkEndian<uint16_t>	flags	{ 0x0000 };
 | 
				
			||||||
 | 
						BAN::NetworkEndian<uint32_t>	ciaddr	{ 0 };
 | 
				
			||||||
 | 
						BAN::NetworkEndian<uint32_t>	yiaddr	{ 0 };
 | 
				
			||||||
 | 
						BAN::NetworkEndian<uint32_t>	siaddr	{ 0 };
 | 
				
			||||||
 | 
						BAN::NetworkEndian<uint32_t>	giaddr	{ 0 };
 | 
				
			||||||
 | 
						BAN::MACAddress					chaddr;
 | 
				
			||||||
 | 
						uint8_t							padding[10] {};
 | 
				
			||||||
 | 
						uint8_t							legacy[192] {};
 | 
				
			||||||
 | 
						BAN::NetworkEndian<uint32_t>	magic_cookie	{ 0x63825363 };
 | 
				
			||||||
 | 
						uint8_t 						options[0x100];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					static_assert(offsetof(DHCPPacket, options) == 240);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum DHCPType
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						SubnetMask = 1,
 | 
				
			||||||
 | 
						Router = 3,
 | 
				
			||||||
 | 
						DomainNameServer = 6,
 | 
				
			||||||
 | 
						RequestedIPv4Address= 50,
 | 
				
			||||||
 | 
						DHCPMessageType = 53,
 | 
				
			||||||
 | 
						ServerIdentifier = 54,
 | 
				
			||||||
 | 
						ParameterRequestList = 55,
 | 
				
			||||||
 | 
						End = 255,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum DHCPMessageType
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						INVALID = 0,
 | 
				
			||||||
 | 
						DHCPDISCOVER = 1,
 | 
				
			||||||
 | 
						DHCPOFFER = 2,
 | 
				
			||||||
 | 
						DHCPREQUEST = 3,
 | 
				
			||||||
 | 
						DHCPDECLINE = 4,
 | 
				
			||||||
 | 
						DHCPACK = 5,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BAN::MACAddress get_mac_address(int socket)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ifreq ifreq;
 | 
				
			||||||
 | 
						if (ioctl(socket, SIOCGIFHWADDR, &ifreq) == -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							perror("ioctl");
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BAN::MACAddress mac_address;
 | 
				
			||||||
 | 
						memcpy(&mac_address, ifreq.ifr_ifru.ifru_hwaddr.sa_data, sizeof(mac_address));
 | 
				
			||||||
 | 
						return mac_address;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void update_ipv4_info(int socket, BAN::IPv4Address address, BAN::IPv4Address subnet)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ifreq ifreq;
 | 
				
			||||||
 | 
							ifreq.ifr_ifru.ifru_addr.sa_family = AF_INET;
 | 
				
			||||||
 | 
							*(uint32_t*)ifreq.ifr_ifru.ifru_addr.sa_data = address.as_u32();
 | 
				
			||||||
 | 
							if (ioctl(socket, SIOCSIFADDR, &ifreq) == -1)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								perror("ioctl");
 | 
				
			||||||
 | 
								exit(1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ifreq ifreq;
 | 
				
			||||||
 | 
							ifreq.ifr_ifru.ifru_netmask.sa_family = AF_INET;
 | 
				
			||||||
 | 
							*(uint32_t*)ifreq.ifr_ifru.ifru_netmask.sa_data = subnet.as_u32();
 | 
				
			||||||
 | 
							if (ioctl(socket, SIOCSIFNETMASK, &ifreq) == -1)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								perror("ioctl");
 | 
				
			||||||
 | 
								exit(1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void send_dhcp_packet(int socket, const DHCPPacket& dhcp_packet, BAN::IPv4Address server_ipv4)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sockaddr_in server_addr;
 | 
				
			||||||
 | 
						server_addr.sin_family = AF_INET;
 | 
				
			||||||
 | 
						server_addr.sin_port = 67;
 | 
				
			||||||
 | 
						server_addr.sin_addr.s_addr = server_ipv4.as_u32();;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sendto(socket, &dhcp_packet, sizeof(DHCPPacket), 0, (sockaddr*)&server_addr, sizeof(server_addr)) == -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							perror("sendto");
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void send_dhcp_discover(int socket, BAN::MACAddress mac_address)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						DHCPPacket dhcp_packet;
 | 
				
			||||||
 | 
						dhcp_packet.op = 0x01;
 | 
				
			||||||
 | 
						dhcp_packet.chaddr = mac_address;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t idx = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = DHCPMessageType;
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = 0x01;
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = DHCPDISCOVER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = ParameterRequestList;
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = 0x03;
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = DomainNameServer;
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = SubnetMask;
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = Router;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = 0xFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						send_dhcp_packet(socket, dhcp_packet, BAN::IPv4Address { 0xFFFFFFFF });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void send_dhcp_request(int socket, BAN::MACAddress mac_address, BAN::IPv4Address offered_ipv4, BAN::IPv4Address server_ipv4)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						DHCPPacket dhcp_packet;
 | 
				
			||||||
 | 
						dhcp_packet.op = 0x01;
 | 
				
			||||||
 | 
						dhcp_packet.siaddr = server_ipv4.as_u32();
 | 
				
			||||||
 | 
						dhcp_packet.chaddr = mac_address;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t idx = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = DHCPMessageType;
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = 0x01;
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = DHCPREQUEST;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = RequestedIPv4Address;
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = 0x04;
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = offered_ipv4.address[0];
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = offered_ipv4.address[1];
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = offered_ipv4.address[2];
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = offered_ipv4.address[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dhcp_packet.options[idx++] = 0xFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						send_dhcp_packet(socket, dhcp_packet, BAN::IPv4Address { 0xFFFFFFFF });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct DHCPPacketInfo
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						enum DHCPMessageType message_type	{ INVALID };
 | 
				
			||||||
 | 
						BAN::IPv4Address address			{ 0 };
 | 
				
			||||||
 | 
						BAN::IPv4Address subnet				{ 0 };
 | 
				
			||||||
 | 
						BAN::IPv4Address server				{ 0 };
 | 
				
			||||||
 | 
						BAN::Vector<BAN::IPv4Address> routers;
 | 
				
			||||||
 | 
						BAN::Vector<BAN::IPv4Address> dns;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DHCPPacketInfo parse_dhcp_packet(const DHCPPacket& packet)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						DHCPPacketInfo packet_info;
 | 
				
			||||||
 | 
						packet_info.address = BAN::IPv4Address(packet.yiaddr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const uint8_t* options = packet.options;
 | 
				
			||||||
 | 
						while (*options != End)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							uint8_t type = *options++;
 | 
				
			||||||
 | 
							uint8_t length = *options++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch (type)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								case SubnetMask:
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (length != 4)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										fprintf(stderr, "Subnet mask with invalid length %hhu\n", length);
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									uint32_t raw = *reinterpret_cast<const BAN::NetworkEndian<uint32_t>*>(options);
 | 
				
			||||||
 | 
									packet_info.subnet = BAN::IPv4Address(raw);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								case Router:
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (length % 4 != 0)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										fprintf(stderr, "Router with invalid length %hhu\n", length);
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									for (int i = 0; i < length; i += 4)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										uint32_t raw = *reinterpret_cast<const BAN::NetworkEndian<uint32_t>*>(options + i);
 | 
				
			||||||
 | 
										MUST(packet_info.routers.emplace_back(raw));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								case DomainNameServer:
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (length % 4 != 0)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										fprintf(stderr, "DNS with invalid length %hhu\n", length);
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									for (int i = 0; i < length; i += 4)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										uint32_t raw = *reinterpret_cast<const BAN::NetworkEndian<uint32_t>*>(options + i);
 | 
				
			||||||
 | 
										MUST(packet_info.dns.emplace_back(raw));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								case DHCPMessageType:
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (length != 1)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										fprintf(stderr, "DHCP Message Type with invalid length %hhu\n", length);
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									switch (*options)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										case DHCPDISCOVER:	packet_info.message_type = DHCPDISCOVER;	break;
 | 
				
			||||||
 | 
										case DHCPOFFER:		packet_info.message_type = DHCPOFFER;		break;
 | 
				
			||||||
 | 
										case DHCPREQUEST:	packet_info.message_type = DHCPREQUEST;		break;
 | 
				
			||||||
 | 
										case DHCPDECLINE:	packet_info.message_type = DHCPDECLINE;		break;
 | 
				
			||||||
 | 
										case DHCPACK:		packet_info.message_type = DHCPACK;			break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								case ServerIdentifier:
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (length != 4)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										fprintf(stderr, "Server identifier with invalid length %hhu\n", length);
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									uint32_t raw = *reinterpret_cast<const BAN::NetworkEndian<uint32_t>*>(options);
 | 
				
			||||||
 | 
									packet_info.server = BAN::IPv4Address(raw);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							options += length;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return packet_info;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BAN::Optional<DHCPPacketInfo> read_dhcp_packet(int socket)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						DHCPPacket dhcp_packet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ssize_t nrecv = recvfrom(socket, &dhcp_packet, sizeof(dhcp_packet), 0, nullptr, nullptr);
 | 
				
			||||||
 | 
						if (nrecv == -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							perror("revcfrom");
 | 
				
			||||||
 | 
							return {};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (nrecv <= (ssize_t)offsetof(DHCPPacket, options))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							fprintf(stderr, "invalid DHCP offer\n");
 | 
				
			||||||
 | 
							return {};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dhcp_packet.magic_cookie != 0x63825363)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							fprintf(stderr, "invalid DHCP offer\n");
 | 
				
			||||||
 | 
							return {};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return parse_dhcp_packet(dhcp_packet);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
 | 
				
			||||||
 | 
						if (socket == -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							perror("socket");
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sockaddr_in client_addr;
 | 
				
			||||||
 | 
						client_addr.sin_family = AF_INET;
 | 
				
			||||||
 | 
						client_addr.sin_port = 68;
 | 
				
			||||||
 | 
						client_addr.sin_addr.s_addr = 0x00000000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (bind(socket, (sockaddr*)&client_addr, sizeof(client_addr)) == -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							perror("bind");
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto mac_address = get_mac_address(socket);
 | 
				
			||||||
 | 
					#if DEBUG_DHCP
 | 
				
			||||||
 | 
						BAN::Formatter::println(putchar, "MAC: {}", mac_address);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						send_dhcp_discover(socket, mac_address);
 | 
				
			||||||
 | 
					#if DEBUG_DHCP
 | 
				
			||||||
 | 
						printf("DHCPDISCOVER sent\n");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto dhcp_offer = read_dhcp_packet(socket);
 | 
				
			||||||
 | 
						if (!dhcp_offer.has_value())
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						if (dhcp_offer->message_type != DHCPOFFER)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							fprintf(stderr, "DHCP server did not respond with DHCPOFFER\n");
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if DEBUG_DHCP
 | 
				
			||||||
 | 
						BAN::Formatter::println(putchar, "DHCPOFFER");
 | 
				
			||||||
 | 
						BAN::Formatter::println(putchar, "  IP     {}", dhcp_offer->address);
 | 
				
			||||||
 | 
						BAN::Formatter::println(putchar, "  SUBNET {}", dhcp_offer->subnet);
 | 
				
			||||||
 | 
						BAN::Formatter::println(putchar, "  SERVER {}", dhcp_offer->server);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						send_dhcp_request(socket, mac_address, dhcp_offer->address, dhcp_offer->server);
 | 
				
			||||||
 | 
					#if DEBUG_DHCP
 | 
				
			||||||
 | 
						printf("DHCPREQUEST sent\n");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto dhcp_ack = read_dhcp_packet(socket);
 | 
				
			||||||
 | 
						if (!dhcp_ack.has_value())
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						if (dhcp_ack->message_type != DHCPACK)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							fprintf(stderr, "DHCP server did not respond with DHCPACK\n");
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if DEBUG_DHCP
 | 
				
			||||||
 | 
						BAN::Formatter::println(putchar, "DHCPACK");
 | 
				
			||||||
 | 
						BAN::Formatter::println(putchar, "  IP     {}", dhcp_ack->address);
 | 
				
			||||||
 | 
						BAN::Formatter::println(putchar, "  SUBNET {}", dhcp_ack->subnet);
 | 
				
			||||||
 | 
						BAN::Formatter::println(putchar, "  SERVER {}", dhcp_ack->server);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dhcp_offer->address != dhcp_ack->address)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							fprintf(stderr, "DHCP server OFFER and ACK ips don't match\n");
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						update_ipv4_info(socket, dhcp_ack->address, dhcp_ack->subnet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (true)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							uint32_t packet = 0x12345678;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sockaddr_in server_addr;
 | 
				
			||||||
 | 
							server_addr.sin_family = AF_INET;
 | 
				
			||||||
 | 
							server_addr.sin_port = 67;
 | 
				
			||||||
 | 
							server_addr.sin_addr.s_addr = dhcp_ack->routers.front().as_u32();
 | 
				
			||||||
 | 
							server_addr.sin_addr.s_addr = (192 << 24) | (168 << 16) | (1 << 8) | 203;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (sendto(socket, &packet, sizeof(packet), 0, (sockaddr*)&server_addr, sizeof(server_addr)) == -1)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								perror("sendto");
 | 
				
			||||||
 | 
								exit(1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						close(socket);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -29,6 +29,12 @@ int main()
 | 
				
			||||||
	if (load_keymap("/usr/share/keymaps/fi.keymap") == -1)
 | 
						if (load_keymap("/usr/share/keymaps/fi.keymap") == -1)
 | 
				
			||||||
		perror("load_keymap");
 | 
							perror("load_keymap");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fork() == 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							execl("/bin/dhcp-client", "dhcp-client", NULL);
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool first = true;
 | 
						bool first = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	termios termios;
 | 
						termios termios;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue