-my $calculate_net_ip4 = sub {
- my ($self, $dhcpreq) = @_;
- my ($req_addr, $network);
-
- $req_addr = $dhcpreq->getOptionValue(DHO_DHCP_REQUESTED_ADDRESS());
- $self->$logger("Req IP: " . ($req_addr ? $req_addr : 'None'));
- if ($req_addr) {
- my ($space, $test);
- my %config = %{$self->{_config}};
- while (my ($net, $opt) = each (%config)) {
- $self->$logger("Network: $net/$opt->{netmask}\n" . Dumper($opt));
- $space = NetAddr::IP->new($net, $opt->{netmask});
- $test = NetAddr::IP->new($req_addr);
- if ($space->contains($test)) {
- $network = $net if ($self->$can_client_use_net_ip4($dhcpreq, $net));
- last;
- }
- }
+my $send_nak = sub {
+ my ($self, $req, $message) = @_;
+
+ $message = 'Bad request' unless $message;
+ my $peeraddr = ($req->ciaddr() && $req->ciaddr() ne inet_ntoa(INADDR_ANY)) ?
+ $req->ciaddr() : inet_ntoa(INADDR_BROADCAST);
+
+ my $sock = IO::Socket::IP->new(
+ Broadcast => 1,
+ PeerPort => 68,
+ PeerAddr => $peeraddr,
+ Proto => 'udp'
+ ) || do {
+ my $err = $@;
+ $self->$logger("[discover_ip4] Socket creation error: $err", ERROR);
+ die "[discover_ip4] Socket creation error: $err\n";
+ };
+
+ my $resp = new Net::DHCP::Packet(
+ Comment => $req->comment(),
+ Op => BOOTREPLY(),
+ Hops => $req->hops(),
+ Xid => $req->xid(),
+ Flags => $req->flags(),
+ Ciaddr => $req->ciaddr(),
+ Yiaddr => "0.0.0.0",
+ Siaddr => $req->siaddr(),
+ Giaddr => $req->giaddr(),
+ Chaddr => $req->chaddr(),
+ DHO_DHCP_MESSAGE_TYPE() => DHCPNAK(),
+ DHO_DHCP_MESSAGE(), $message,
+ );
+
+ $self->$logger("Sending NAK to " . $sock->peerhost . ':' . $sock->peerport .
+ "\nReason: $message", INFO);
+ $self->$logger($resp->toString());
+
+ my $xid = $req->xid() ? $req->xid() : 'Missing';
+ $self->$logger("Sending OFFER tr=$xid", INFO);
+
+ $sock->send($resp->serialize()) || die "Error sending OFFER: $!\n";
+ $sock->close;
+};
+
+my $send_accept = sub {
+ my ($self, $req, $calc_ip, $reply) = @_;
+ my $msg;
+
+ my $peeraddr = ($req->ciaddr() && $req->ciaddr() ne inet_ntoa(INADDR_ANY)) ?
+ $req->ciaddr() : inet_ntoa(INADDR_BROADCAST);
+
+ if ($reply == DHCP_OFFER) {
+ $reply = DHCPOFFER();
+ $msg = 'DHCP_OFFER';
+ } elsif ($reply == DHCP_ACK) {
+ $reply = DHCPACK();
+ $msg = 'DHCP_ACK';