The sr function in the official API documentation:
sr(pkts, filter=None, iface=None, timeout=2, inter=0, verbose=None, chainCC=0, retry=0, multi=0)
Send and receive packets at level 3 with the super conf.L3socket .
srp function:
srp(pkts, filter=None, iface=None, timeout=2, inter=0, verbose=None, chainCC=0, retry=0, multi=0, iface hint=None)
Same as srp , but for working at level 2 with supersocket conf.L2socket .
Since your ICMP packet also populates the fields of layer 2, as shown in the output of ICMP.show2() , you should use the srp function. If you left them untouched, as you did in this tutorial , you could use the sr function.
Now about your question about classifying ICMP as a layer 2 protocol or a layer 3 protocol. Many people consider this a layer 3 protocol, for example here , because it uses the IP header and sits on top of it. However, others consider this to be a layer 2 protocol, such as here . This is a question with some good answers to this problem, but note that they relate to the OSI , so the numbering of the layer scheme is slightly different. This is the best I managed to find, from here :
IP itself does not have a mechanism for establishing and maintaining a connection, or even contains data as a direct payload. The Internet Control Messaging Protocol is just an IP add-on for error transport, routing, and messaging and data management and is often considered a network layer protocol.
EDIT - I just met this link and thought it worth mentioning:
ICMP is a protocol in the TCP / IP stack that exists primarily for monitoring, troubleshooting, and error messages. It works over IP, such as TCP and UDP, but is a network layer protocol, such as IP, and not a transport layer protocol, such as TCP and UDP. (Yes, it is strange that ICMP is encapsulated in IP, at the same level as IP. But again, you can encapsulate an IP address in IP.)
RFC 792 is also pretty explicit:
ICMP uses basic IP support as if it were a higher layer protocol, but ICMP is actually an integral part of IP.
And so RFC 1122 :
ICMP is a management protocol that is considered an integral part of IP, although it has an architectural layer on IP, i.e. uses IP to transfer its data from one end to the other, like a transport protocol such as TCP or UDP does.
...
Although ICMP messages are encapsulated in IP datagrams, ICMP processing is considered (and usually implemented as) part of the IP layer.
As for your last question about explicitly specifying an interface, see the scapy tutorial :
The send() function will send packets at level 3. That is, it will handle routing and level 2 for you. The sendp() function will work at level 2. For you, you need to select the correct interface and protocol of the correct channel level.
The official API documentation is a bit more detailed:
When Scapy is launched, its routing tables are synchronized with the host routing table. For a packet sent at layer 3, the destination IP address determines the output interface, source address, and gateway to be used. For a Level 2 packet, the output interface can be refined, or the prompt can be specified as IP to determine the output interface. If there is no output interface or tooltip, conf.iface used.
In particular, the iface parameter iface used to set the input interface (but also sets the output interface if iface_hint not used):
iface: listen to answers only on the provided interface
For a hint of the output interface, use iface_hint for level 2 functions:
There is also an optional iface_hint parameter that provides a hint that can help you choose the right output interface. By default, if iface is not specified, conf.iface selected. The tooltip takes the form of an IP address to which a Level 2 packet can be assigned. The Scapy routing table ( conf.route ) is used to determine which interface to use to reach this IP address.