This entry is part 5 of 11 in the series Building Network Tools with Scapy

With a good understanding of how to view our packets we can now move onto some packet generation. Let’s talk a bit about sniffing first and how existing packets are our best tool for creating new ones.

Sniff() function arguments

We’ve used the sniff() function a couple times already to capture some packets for viewing. I’m going to explain a little bit more about the sniff() function and its arguments. The arguments we will be talking about are:

  • count: Number of packets to capture. 0 means infinity.
  • iface: Sniff for packets only on the provided interface.
  • prn: Function to apply to each packet. If something is returned, it is displayed. For instance you can use prn = lambda x: x.summary().
  • store: Whether to store sniffed packets or discard them. When you only want to monitor your network forever, set store to 0.
  • timeout: Stop sniffing after a given time (default: None).

These should all be self-explanatory except for the filter and prn arguments. The filter argument takes BPF syntax filters, just like Wireshark or tcpdump capture filters. The prn argument is a very cool capability of the sniff() function and you can read more about it here: Scapy and custom actions.

Since we want to generate our first ARP packet we should go ahead and sniff one to see what it takes to recreate one using the .show() and .command() method. Here’s a sniff using the count and filter arguments:


Building a Packet

It looks like ARP packets only have 2 layers plus padding that we have to worry about. We can use the ls() function on the Ether and ARP layers to see what options are available to us:


Let’s create our ARP packet and start assigning some values. We can use Python’s eval() function to initiate our packet with the string returned from the .command() method. Also, since we know that packets are mutable dictionaries, we can just use the assignment operator to assign our desired values to specific fields:


The layers we want are defined with the with the Layer() notation. This will work for any layer in the ls() command output. That’s a lot of options! You can also define the packet from scratch with all the options in one statement by passing in the fields as arguments to the related layer.

Note that the special glue holding these packets together is the / operator. If you happen to forget a layer when you’re first defining the packet, you can add on a layer very easily using the existing packet and the / operator like this:


Sending a packet

Yup, you guessed it, its finally time to send this ARP packet out on the wire! Since ARP is a L2 protocol we’re going to use the sendp() function as the send() function only works with L3 Packets (IP or IPv6 headers):


Screenshot of capture packet in Wireshark

Screenshot of capture packet in Wireshark

What, what! Check that out! Our packet out from the scapy console and in the wire! Pretty cool, right? Well, here’s a fun fact. We don’t need to create and build the packet before sending it, we can define the packet right there in the send() or sendp() function like this:


In fact, we can do some other cool things with these send functions. If we had an array of packets (such as one created with Python loops and some random or incrementing values for IP address/TCP port), the send function would send each packet in that array:


The send commands have some arguments to control the packet sending, here’s the main ones you might consider using:

send(pkts, inter=0, loop=0)
sendp(pkts, inter=0, loop=0)

  • iface: The interface to send the packets out from.
  • inter: Time in seconds to wait between 2 packets.
  • loop: Send the packets endlessly if not 0.
  • pkts: Can be a packet, an implicit packet or a list of them.
Series Navigation<< Scapy p.04 – Looking at PacketsScapy p.06 – Sending and Receiving with Scapy >>

This article has 8 comments

  1. Diamond

    Another question that I forgot, is if I set destination IP addresses locally, it give an error like “Mac address to reach destination not found. Using broadcast”

    What should I do?

    Thanks in advance

    1. matw

      I’m not familiar with running python or scapy on Windows, but you can check out instructions for installing and running scapy in Windows here.

      Regarding the broadcast error, check out the explanation here. You might need to use the L2 sendp() function instead of send() and set the src and dest MAC address manually.

      Also, Stack Overflow has an excellent community and several scapy experts with a lot more experience than me. I highly recommend checking this site out, it’s a great resource!

  2. Kashif


    I am trying to send the packets via scapy. It says that the packet is sent but I can’t really capture it via wireshark. I am using windows version of scapy. Can you shed some light on that?

Leave a Reply

Your email address will not be published. Required fields are marked *