Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

ARP Lookups

by WalkingZero (Sexton)
on May 25, 2008 at 13:58 UTC ( #688406=perlquestion: print w/ replies, xml ) Need Help??
WalkingZero has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks, I am trying to write a function that, given an array of IP addresses, will run ARP requests to find out which IPs are currently assigned to live hosts. I am in need of some pointing in the right direction for propper tools/modules to use. I tried Net::ARP however it primarily reads the ARP cache which does not provide up-to-date information. also it's packet construction requires a target MAC address. If I had the MAC address I wouldn't need to send the request ;). What I actually need is to create broadcast packets of "Who has <ip address>" and then listen for the replies. I think Net::Pcap is probably half of what I need. If someone can point me to a good way to do the requests, and/or tell me if Net::Pcap is really what I should be messing with here, I'd appreciate it. Cheers!

UPDATE: Well as per my other post at Net::Pcap garbage Output Pcap has not worked out well for me so far. I think I am going to try approaching this from a different angle in my obvious lack of full understanding of Pcap. I'm going to try using Net::Frame::Dump to tackle this problem instead.

Update #2: : It would appear that the garbage output I was getting was from the NetPacket decode functions and I was mistakingly attributing them to Pcap due to the decimal converted values it was giving me in the lookup command. I switched over to using Net::Frame::Dump::Online and Net::Frame::Simple. After some leg work I have gotten this to work. code attached if anyone cares to comment

#!/usr/bin/perl use Net::ARP; use Net::Netmask; use Net::Frame::Simple; use Net::Frame::Dump::Online; my $dev= "eth1"; $interface= shift; $ifconf= `ifconfig $dev`; $ifconf=~ /\d+\.\d+\.\d+\.\d+/; $ipdec= $&; $ifconf=~ /Mask:\d+\.\d+\.\d+\.\d+/; $nmaskdec= $&; $nmaskdec=~s/Mask://; my $netblock= $ipdec . ":" . $nmaskdec ; $netmask=new Net::Netmask ($netblock); my @iprange = $netmask->enumerate; $arpDump=Net::Frame::Dump::Online->new( dev => $dev, filter => 'arp'); $arpDump->start; my %livehosts; my $reply; $counter=0; while ($counter<3){ for $ipts (@iprange){ Net::ARP::send_packet($dev,$ipdec,$ipts,"00:18:de:34:8e:7b","f +f:ff:ff:ff:ff:ff","request"); } until ($arpDump->timeout){ if ($next=$arpDump->next){ my $r=Net::Frame::Simple->newFromDump($next); $opc=$r->ref->{ARP}->opCode; next unless $opc == 2; $livehosts{$r->ref->{ARP}->srcIp}=$r->ref->{ARP}->src; } } $arpDump->timeoutReset; $counter++; } foreach $key (keys %livehosts){ print "IP Address $key is up with mac of $livehosts{$key} \n"; }

Comment on ARP Lookups
Download Code
Re: ARP Lookups
by kyle (Abbot) on May 25, 2008 at 14:14 UTC
    If you ping the host, that will generate an ARP request. If the host responds to ping, you can stop there. Otherwise look in the ARP cache.
      I ammend my previous reply slightly. If ICMP Blocking is turned on, the ARP request will still go out. however, I still find that I cannot rely on the ARP cache as the source of my information, especially as in Linux the only way to reliably clear an arp cache is to bring the interface down and back up. So in the end, I still feel that dealing with a raw ARP Request and Reply over the wire is the best way to accomplish my ends. Thank you though.
Re: ARP Lookups
by Anonymous Monk on May 25, 2008 at 14:49 UTC
    Net::ARP however it primarily reads the ARP cache which does not provide up-to-date information. also it's packet construction requires a target MAC address.

    So make it the broadcast address?

      .......well I feel stupid. I totally forgot that there was a broadcast MAC just like a broadcast IP address.
Re: ARP Lookups
by grinder (Bishop) on May 25, 2008 at 14:56 UTC

    I wouldn't bother with Perl at all in this case. A much better solution for scanning large networks and seeing what's alive is thcrut.

    Plus, it will give you a pretty good idea of what's behind the MAC address, since it correlates addresses with vendor information. You'll find it much faster to read the output out of a backticked sub process in a while loop, and scrape the output to get what you need, than trying to do it yourself any other way.

    • another intruder with the mooring in the heart of the Perl

      Grinder: Thank you for the pointer to what looks like yet another wonderful tool. I should explain however, that I am trying to do this as an educational/hobbyist experience type of deal. So the end result isn't so much important as learning how to get there =) My perl knowledge is pretty much all self learned through Oreilly Books, Perlmonks, and painful trial and error. I know this will generate naysayers who will tell me "give up this is too advanced for you" but frankly I don't care. The act of figuring it all out is what is important to me here, not making the greatest piece of software ever or trying to prove I am a great programmer(cus I'm not)

        WalkingZero writes:

        I am trying to write a function that, given an array of IP addresses, will run ARP requests to find out which IPs are currently assigned to live hosts.
        If that's all you are trying to do then send some packet to the host that you think it will respond to and, if it responds, then your ARP cache is correct. Look in the ARP cache for the MAC.
        I think Net::Pcap is probably half of what I need.
        Not likely.
        I still feel that dealing with a raw ARP Request and Reply over the wire is the best way to accomplish my ends.
        If you use a perl module to construct a packet to send then most such modules also will provide a way to deconstruct the packet you receive. For ARP packets you might try NetPacket::ARP. Claims to do what you need. You'll have to open a socket to your destination to send the packets formated by NetPacket::ARP.



        s//----->\t/;$~="JAPH";s//\r<$~~/;{s|~$~-|-~$~|||s |-$~~|$~~-|||s,<$~~,<~$~,,s,~$~>,$~~>,, $|=1,select$,,$,,$,,1e-1;print;redo}

      > I wouldn't bother with Perl at all in this case. A much better solution for scanning large networks and seeing what's alive is thcrut.

      I've just tried to compile 'thcrut' in a sandbox - pure curiosity, since I've got a Perl script that does host discovery for me - and I've got to say that the message at the end of running 'configure' does not inspire much confidence in me.

      [...] Preprocessor flags: -I../pcre-3.9 -I../Libnet-1.0.2a/include -I/usr/l +ocal/include Linker flags: -L../pcre-3.9 -L../Libnet-1.0.2a/src -L/usr/local +/lib Libraries: -L/usr/local/lib -lpcre -lnet -lpcap -lnsl + _ + _( (~\ _ _ / + ( \> > \ -/~/ / ~\ :; \ +_ > /(~\/ || | | /\ ;\ |l _____ |; ( + \/ > > --------. _\\)\)\)/ ;;; `8o __-~ ~\ d| + \ // * HELP * | ///(())(__/~;;\ "88p;. -. _\_;.oP + (_._/ / * HELP * | (((__ __ \\ \ `>,% (\ (\./)8" + ;:' i | )))--`.'-- (( ;,8 \ ,;%%%: ./V^^^V' + ;. ;. I'M JUST | ((\ | /)) .,88 `: ..,,;;;;,-::::::'_::\ ||\ + ;[8: ; STUPID ! )| ~-~ |(|(888; ..``'::::8888oooooo. :\`^^^/,,~--._ + |88:: | WHITEHAT.|_____-===- /| \8;; ``:. oo.8888888888:`((( o.ooo8888O +o;:;:' | |. |_~-___-~_| `-\. ` `o`88888888b` )) 888b88888P +""' ; PLEASE | ; ~~~~;~~ "`--_`. b`888888888;(.,"888b888" +..::;-' DONT HURT | ; ; ~"-.... b`8888888:::::.`8888. .:; +;;'' MEEEEEE! | ; ; `:::. `:::OOO:::::::.`OO' ;;;' +' | : ; `. "``::::::'' .' * HELP * | ; `. \_ / * HELP * | ; ; +: ~~-- `:' -'; __________! `: : .::/ -Tua +Xiong ; ;;+_ :::. :..;;; -=[ (C) THE HACKERS CHOICE - Estd. 1995 ]=- -=[ www.ircsnet.net /j #TH +C ]=- ------=[ WHQ: http://www.thc.org ]=- - -=[ Enjoy your enemy... ]=----- +----- Configuration complete. Now type: make all install; thcrut -h

      I don't know about you, but I'd much rather "bother" with a Perl script - especially since you'd need to run 'thcrut' as root to get any useful action. I'll leave the dubious pleasure of carefully vetting several hundred K of C code to someone else.

      
      -- 
      Human history becomes more and more a race between education and catastrophe. -- HG Wells
      

        It's a tool. Granted, that dopey ASCII art thing is pretty dumb, but I got over it, and it's a valuable addition to my toolbox.

        You may not realise that to do lots of useful things, you need to be root. Had a look at ping(1) recently? It's setuid root, because only root may issue icmp packets.

        And your firewall will of course block any egress attempts from the host on which you run this program, right? I doubt there's a rootkit in there, but I haven't looked closely. I imagine that if there was anything fishy going on, we would have heard about it by now.

        • another intruder with the mooring in the heart of the Perl

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://688406]
Approved by grep
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (10)
As of 2014-07-22 09:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (109 votes), past polls