#!/usr/bin/perl # luna@aditel.org # use IO::Socket::INET; use Net::DHCP::Packet; use Net::DHCP::Constants; use IO::Select; ###CONFIG HERE my($iface)="eth0"; my($timeout)="10"; #Timeout in seconds ##################### #Some dhcp servers needs mac address in the msg to match with layer 2 information... #Getting our own mac address... (ioctl way is so platform dependent... :P) $iface=quotemeta($iface); $mymac=`/sbin/ifconfig $iface |grep HW`; chomp($mymac); $mymac=~ s/.*(.{2}):(.{2}):(.{2}):(.{2}):(.{2}):(.{2}).*/$1$2$3$4$5$6/g; # creat DHCP Packet $discover = Net::DHCP::Packet->new( xid => int(rand(0xFFFFFFFF)), # random xid Flags => 0x8000, # ask for broadcast Chaddr=>$mymac, DHO_DHCP_MESSAGE_TYPE() => DHCPDISCOVER() ); #Sender socket $handle = IO::Socket::INET->new(Proto => 'udp', Broadcast => 1, PeerPort => '67', LocalPort => '68', PeerAddr => '255.255.255.255', ReuseAddr=>1) or die "socket: $@"; # yes, it uses $@ here #Receiver socket (should bind to ANY addres,(response may come as broadcast)) $bsock = IO::Socket::INET->new(LocalPort => 68, Proto => "udp", Broadcast => 1, ReuseAddr=>1) or die "socket: $@"; $control=new IO::Select($bsock); #Send dhcp discover $handle->send($discover->serialize()) or die "Error sending broadcast inform:$!\n"; #Receive responses my(%servers); while ($control->can_read($timeout)) { $bsock->recv($newmsg, 1024); $packet = Net::DHCP::Packet->new($newmsg); # print STDERR $packet->toString(); my($ip1, $ip2, $ip3, $ip4)=unpack("CCCC",$packet->getOptionRaw(DHO_DHCP_SERVER_IDENTIFIER())); $servers{"$ip1.$ip2.$ip3.$ip4"}=1; } print "Active DHCP server(s) on the network: ".join(",",keys(%servers))."\n";