In the previous article I demonstrated how to add a custom function to change the formatting of the packet output in the console or do some sort of custom action with each packet. The limitation of just including a function name in the prn argument is that you cannot pass along any arguments other than the packet itself (implicitly passed).

Using nested functions to harness the power of closure, you can bind any number of arguments to the function that is executed on each packet by Scapy. From the part 1 article, you can see how we created a function and used the function to pass the actual function (not the returned value) to the prn argument:


It is very clear to see that the implicitly passed packet object from scapy will be the parameter in the customActions function. But if we try to send in a parameter such as the url variable, we’ll get an error that custom_action only takes 1 parameter. In order to bind additional arguments to the function, we have to use nested functions. Check out this example, created to upload the scapy packet info to an API via the Python Requests module:


This may seem a little strange, but here’s an order-of-events explanation for what’s happening:

  1. We define our url & token variables, just like in the first example.
  2. We define the custom_action function. This will be run when the scapy sniff function first runs to get the value info for the prn argument. Note the two parameters that we pass into custom_action.
  3. Inside custom_action, we create another function that takes the scapy implicitly passed packet as a parameter. This is the function that will upload the packet info to our API.
  4. The upload_packet function is nested in custom_action so it has access to the url & token variables because it is inside the parent function’s scope.
  5. The return value of custom_action is the upload_packet function, so this function will be run along with every sniffed packet based on the prn argument. Even though the custom_action function is not executed to take in the url & token parameters, they are locked into the nested upload_packet function due to Python’s capacity for ‘closure’.
  6. After we define the custom_action and nested upload_packet functions, we run the Scapy sniff function with the returned value of custom_action passed via the prn argument.

Using closures to ‘lock-in’ any number of arguments to the custom_action function gives us much more flexibility. I was able to modularize my file in order to clean up my Scapy sniffing script. Here’s another example passing the API options in as an object instead of multiple arguments:


See how I was able to move a big chunk of verbose packet protocol checking into a separate module by looking at my two python files in this project: Scapy-to-API

This article has 1 comments

  1. Pingback: Scapy p.07 – Monitoring ARP | thePacketGeek

Leave a Reply

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