#!/usr/bin/perl # Simple DHCP client - sending a broadcasted DHCP Discover request use strict; use warnings; use IO::Socket::IP -register; use Net::DHCP::Packet; use Net::DHCP::Constants; use POSIX qw(setsid strftime); my ($request, $send, $receive, $discover, $response, $buf, $serverip, $myip, $mymac, $hostname); $mymac = qx/ \/sbin\/ifconfig | grep -P '^eth0.+HWaddr\\s*' | awk '{print \$5}' /; $mymac =~ tr/://d; chomp($hostname = `hostname -s`); # Overrule when testing #$mymac = '001cc0c33317'; logger("mac: $mymac"); # sample logger sub logger{ my $str = shift; print STDOUT strftime "[%d/%b/%Y:%H:%M:%S] ", localtime; print STDOUT "$str\n"; } logger("DHCPd tester - dummy client"); logger("Opening socket"); $send = IO::Socket::IP->new( Proto => 'udp', Broadcast => 1, PeerPort => 'bootps(67)', #PeerAddr => inet_ntoa(INADDR_LOOPBACK),#(INADDR_BROADCAST), PeerAddr => inet_ntoa(INADDR_BROADCAST), ) || die "Socket (send) creation error: $@\n"; # yes, it uses $@ here # create DHCP Packet DISCOVER my $xid = int(rand(0xFFFFFFFF)); $discover = Net::DHCP::Packet->new( Chaddr => $mymac, Giaddr => $send->sockhost(), Xid => $xid, # random xid DHO_DHCP_MESSAGE_TYPE() => DHCPDISCOVER(), Flags => 0x8000, DHO_VENDOR_CLASS_IDENTIFIER() => 'foo', DHO_HOST_NAME() => $hostname, ); logger("Sending DISCOVER to " . $send->peerhost . ":" . $send->peerport); logger($discover->toString()); $send->send($discover->serialize(), 0) or die "Error sending:$!\n"; $receive = IO::Socket::IP->new( Proto => 'udp', Broadcast => 1, LocalPort => 'bootpc(68)', #LocalAddr => inet_ntoa(INADDR_LOOPBACK),#(INADDR_ANY), LocalAddr => inet_ntoa(INADDR_ANY), ) || die "Socket (receive) creation error: $@\n"; # yes, it uses $@ here logger("Listen: " . $receive->sockhost . ":" . $receive->sockport); logger("Waiting for response from server"); $receive->recv($buf, 1024, 0); logger("Got response from " . $receive->peerhost . ":" . $receive->peerport); $receive->close; $response = new Net::DHCP::Packet($buf); if ($response->getOptionValue(DHO_DHCP_MESSAGE_TYPE()) == DHCPNAK()) { logger("Request for ip was denied"); exit; } $serverip = $response->getOptionValue(DHO_DHCP_SERVER_IDENTIFIER()); $myip = $response->yiaddr(); logger($response->toString()); # create DHCP Packet REQUEST $request = Net::DHCP::Packet->new( Xid => $xid, # random xid Chaddr => $mymac, Giaddr => $send->sockhost(), DHO_DHCP_MESSAGE_TYPE() => DHCPREQUEST(), DHO_VENDOR_CLASS_IDENTIFIER() => 'foo', DHO_HOST_NAME() => $hostname, DHO_DHCP_REQUESTED_ADDRESS() => $myip, ); logger("Sending REQUEST to " . $send->peerhost . ":" . $send->peerport); logger($request->toString()); $send->send($request->serialize()) or die "Error sending:$!\n"; $send->close; $receive = IO::Socket::IP->new( Proto => 'udp', Broadcast => 1, LocalPort => 'bootpc(68)', #LocalAddr => inet_ntoa(INADDR_LOOPBACK),#inet_ntoa(INADDR_ANY), LocalAddr => inet_ntoa(INADDR_ANY), ) || die "Socket creation error: $@\n"; # yes, it uses $@ here logger("Waiting for response from server"); $receive->recv($buf, 1024, 0); logger("Got response from " . $receive->peerhost . ":" . $receive->peerport); $receive->close; $response = new Net::DHCP::Packet($buf); logger($response->toString()); if ($response->getOptionValue(DHO_DHCP_MESSAGE_TYPE()) == DHCPACK()) { $send = IO::Socket::IP->new( Proto => 'udp', Broadcast => 1, PeerPort => 'bootps(67)', PeerAddr => $serverip, ) || die "Socket (send) creation error: $@\n"; # yes, it uses $@ here # create DHCP Packet REQUEST $request = Net::DHCP::Packet->new( op => BOOTREQUEST(), Xid => int(rand(0xFFFFFFFF)), # random xid Chaddr => $mymac, Ciaddr => $myip, Giaddr => $send->sockhost(), DHO_VENDOR_CLASS_IDENTIFIER() => 'foo', DHO_HOST_NAME() => $hostname, DHO_DHCP_MESSAGE_TYPE() => DHCPRELEASE() ); logger("Sending REQUEST to " . $send->peerhost . ":" . $send->peerport); logger($request->toString()); $send->send($request->serialize()) or die "Error sending:$!\n"; $send->close; } else { logger("Request for ip $myip was denied") }