--- /dev/null
+#!/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);
+
+$mymac = qx/ \/sbin\/ifconfig | grep -P '^eth0.+HWaddr\\s*' | awk '{print \$5}' /;
+$mymac =~ tr/://d;
+
+# 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),
+ )
+ || die "Socket (send) creation error: $@\n"; # yes, it uses $@ here
+
+# create DHCP Packet DISCOVER
+$discover = Net::DHCP::Packet->new(
+ Chaddr => $mymac,
+ Giaddr => $send->sockhost(),
+ Xid => int(rand(0xFFFFFFFF)), # random xid
+ DHO_DHCP_MESSAGE_TYPE() => DHCPDISCOVER(),
+ Flags => 0x8000,
+ DHO_VENDOR_CLASS_IDENTIFIER() => 'foo',
+ );
+
+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),
+ )
+ || 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);
+$serverip = $response->getOptionValue(DHO_DHCP_SERVER_IDENTIFIER());
+$myip = $response->yiaddr();
+
+logger($response->toString());
+
+# create DHCP Packet REQUEST
+$request = Net::DHCP::Packet->new(
+ Xid => int(rand(0xFFFFFFFF)), # random xid
+ Chaddr => $mymac,
+ Giaddr => $send->sockhost(),
+ DHO_DHCP_MESSAGE_TYPE() => DHCPREQUEST(),
+ DHO_VENDOR_CLASS_IDENTIFIER() => 'foo',
+ 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),
+ )
+ || 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_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")
+}