maclaren_sg has asked for the wisdom of the Perl Monks concerning the following question:

I've gotten the below code to test if my DHCP server is work or not. However, there is some problem to it. If the DHCP reply is broadcast, the script will never responds. It is only when a unicast reply, the scripts will have response and terminates.
#!/usr/bin/perl # Simple DHCP client - sending a broadcasted DHCP Discover request use IO::Socket::INET; use Net::DHCP::Packet; use Net::DHCP::Constants; use POSIX qw(setsid strftime); # 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"); $handle = IO::Socket::INET->new(Proto => 'udp', Broadcast => 1, PeerPort => '67', LocalPort => '68', PeerAddr => '255.255.255.255', ) || die "Socket creation error: $@\n"; # yes, it uses $@ here # create DHCP Packet DISCOVER $discover = Net::DHCP::Packet->new( Xid => 0x12345678, DHO_DHCP_MESSAGE_TYPE() => DHCPDISCOVER(), DHO_VENDOR_CLASS_IDENTIFIER() => 'foo', ); logger("Sending DISCOVER to 127.0.0.1:67"); logger($discover->toString()); $handle->send($discover->serialize()) or die "Error sending:$!\n"; logger("Waiting for response from server"); $handle->recv($buf, 4096) || die("recv:$!"); logger("Got response"); $response = new Net::DHCP::Packet($buf); logger($response->toString()); # create DHCP Packet REQUEST $request = Net::DHCP::Packet->new( Xid => 0x12345678, Ciaddr => $response->yiaddr(), DHO_DHCP_MESSAGE_TYPE() => DHCPREQUEST(), DHO_VENDOR_CLASS_IDENTIFIER() => 'foo', DHO_DHCP_REQUESTED_ADDRESS() => $response->yiadd +r(), ); logger("Sending REQUEST to 127.0.0.1:67"); logger($request->toString()); $handle->send($request->serialize()) or die "Error sending:$!\n"; logger("Waiting for response from server"); $handle->recv($buf, 4096) || die("recv:$!"); logger("Got response"); $response = new Net::DHCP::Packet($buf); logger($response->toString());

Replies are listed 'Best First'.
Re: Socket Listen/Send DHCP
by drip (Beadle) on Oct 11, 2008 at 10:36 UTC
    I find it easy to use Net::PcapUtils when capturing packets..

    here's a part of the module(for dhcp testing) i am trying to finish..

    sub getreply{ my $self=shift; my $packetcap1= Net::PcapUtils::open( FILTER =>'udp dst port 6 +8' , DEV => $self->{INTERFACE}, SNAPLEN => 400); my ($packetcap)=Net::PcapUtils::next($packetcap1); my $ethpack=NetPacket::Ethernet->decode($packetcap); my $ipack=NetPacket::IP->decode($ethpack->{data}); my $udpack=NetPacket::UDP->decode($ipack->{data}); my $capture=Net::DHCP::Packet->new($udpack->{data}); my $smac=sprintf ($ethpack->{src_mac}); my $dmac=sprintf ($ethpack->{dest_mac}); my $srcmac= sprintf("%s%s:%s%s:%s%s:%s%s:%s%s:%s%s", split//, +$smac); my $destmac= sprintf("%s%s:%s%s:%s%s:%s%s:%s%s:%s%s", split//, + $dmac); print ("====================BOOT REPLY======================== +\n"); print "\n"; print $ipack->{src_ip} . "=====>" . $ipack->{dest_ip} . "(id : + $ipack->{id}, ttl: $ipack->{ttl})" . "\n"; print "UDP Source: $udpack->{src_port} ==> UDP Destination: $ +udpack->{dest_port} \n"; print "UDP Length: $udpack->{len}, UDP Data Length:", length($ +udpack->{data})," \n"; print "UDP Checksum: $udpack->{cksum} \n"; print "\n"; print "Source Mac address is : ".$srcmac."=====>"; print "Destination Mac address is: " . $destmac."\n"; my $ethtype=sprintf("%0.4x", $ethpack->{type}); print "Ethertype: ". $ethtype . "\n"; print "\n"; print ("====================UDP PACKET======================== +\n"); print $capture->toString()."\n"; return $ipack; }

    Hope you find it useful..

    Cheers,
    drip
Re: Socket Listen/Send DHCP
by bingos (Vicar) on Oct 11, 2008 at 08:23 UTC

    I freely admit to cargo-culting this, but I use the following in POE::Component::DHCP::Monitor to put the sockets into promiscuous mode.

    setsockopt( $dhcp_socket, SOL_SOCKET, SO_BROADCAST, 1 );
      Thanks, but isn't there a way to solve the problem istead of working around?
      Kind of messy, and the thing lies with Sock::INET, when PeerAddr is set, it will only listens to packets with its own IP.