in network, python

How to understand the ARP queries and replies fields with pypcap

I had a hard time understanding the function of each field in an ARP packet. The problem is that the fields change of meaning, depending on the opcode field. The two useful ones are for ARP queries (what is the ethernet address of the ip address I’m giving now) and ARP replies (that ip address is located at this ethernet address).

So to fix this problem once for all, I decided to write a python script that shows the different field values when an ARP packet is captured.

There are several libraries available to the pythonista to manipulate network packets. The most known is certainly pylibpcap which is quite old now, and not really object oriented. It is more an adaptation one-to-one of the C libpcap library, which may be useful for some people.
Another library is pypcap, which is like pylibpcap, but much much more object oriented.
pypcap includes a huge quantity of protocols definitions, so it’s really cool to use, especially because it also includes a network packet capture method. There is no included method to send packets, but there are examples of how to do this in the test files.
Another possibility is scapy, which is an extremely complete program (more a program than a library, even though you can use it as a module). The fact that it’s not that easy to include scapy in my own program, even though there’s now a howto. My program doesn’t need all the bells and whistles given by scapy, so I settled on pypcap.

import dpkt, pcapfrom socket import inet_ntoa

def ether_decode(p):
return ':'.join(['%02x' % ord(x) for x in str(p)])

if __name__ == '__main__':
iface_name = 'eth1' # Here set your listening interface
pc = pcap.pcap(iface_name)
pc.setfilter('arp')

for ts,pkt in pc:
packet = dpkt.ethernet.Ethernet(pkt)

print "ARP packet received:"
print "op=%d" % packet.data.op
print "src=%s" % ether_decode(packet.src)
print "dst=%s" % ether_decode(packet.dst)
print "spa=%s" % inet_ntoa(packet.data.spa)
print "tpa=%s" % inet_ntoa(packet.data.tpa)
print "tha=%s" % ether_decode(packet.data.tha)
print "sha=%s" % ether_decode(packet.data.sha)
print

That’s it. Now, for example, 192.168.4.3 wants to get 192.168.4.254’s ethernet address (192.168.4.254 has 00:90:4c:49:00:2a address and 192.168.4.3 has 00:50:70:b4:19:0c), here is the output:


ARP packet received:op=1 src=00:50:70:b4:19:0c dst=ff:ff:ff:ff:ff:ff
spa=192.168.4.3 tpa=192.168.4.254 tha=00:00:00:00:00:00sha=00:50:70:b4:19:0c
ARP packet received:op=2 src=00:90:4c:49:00:2a dst=00:50:70:b4:19:0c
spa=192.168.4.254 tpa=192.168.4.3 tha=00:50:70:b4:19:0csha=00:90:4c:49:00:2a