Question

I would like to send IGMP packets using scapy, specifically IGMP Leave, IGMP Membership report. Is it possible to do so?

UPDATE:

I was able to eventually generate them. Had to do the following:

1) Install scapy v.2.2.0 as it's described here (including minor alteration in setup.py): scapy's contrib is missing after installing scapy on both windows and fedora

2) You need to use file from contribution package (features not added to the core of scapy):

import scapy.contrib.igmp
igmpPacket = scapy.contrib.igmp.IGMP()
Was it helpful?

Solution

Yes, it is possible to send IGMP packets. After googling a bit, I came up with some useful links that can help you in some direction. On github there exists a IGMP and IGMPv3 implementation in scapy. Here is an interesting mailing list too. Also, this post has an other interesting stuff related to IGMP.

OTHER TIPS

With this method, you can send out IGMP version 2 (RFC2236) Membership Query message, not IGMP version 3.

Here are complete code and tcpdump:

>>> from scapy.all import *
>>> import scapy.contrib.igmp
>>> p = IP(dst="62.22.14.4")/scapy.contrib.igmp.IGMP()
>>> send(p)
.
Sent 1 packets.
>>>

# tcpdump -ni cplane0 igmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on cplane0, link-type EN10MB (Ethernet), capture size 262144 bytes
18:42:01.045618 IP 44.60.11.3 > 62.22.14.4: igmp query v2 [max resp time 20]
18:42:01.045631 IP 44.60.11.3 > 62.22.14.4: igmp query v2 [max resp time 20]
18:42:01.046470 IP 44.60.11.3 > 62.22.14.4: igmp query v2 [max resp time 20]
18:42:01.046476 IP 44.60.11.3 > 62.22.14.4: igmp query v2 [max resp time 20]
18:42:01.959331 IP 62.22.14.4 > 224.1.1.1: igmp v2 report 224.1.1.1

Update: Since IGMPv3 is under construction. Here is a way to send IGMP version 3 Membership Query:

>>> from scapy.all import *
>>>
>>> class IGMP3(Packet):
...     name = "IGMP3"
...     fields_desc = [ ByteField("type", 0x11),
...                     ByteField("mrtime", 20),
...                   XShortField("chksum", None),
...                       IPField("gaddr", "0.0.0.0"),
...                      IntField("others", 0x0)]
...     def post_build(self, p, pay):
...         p += pay
...         if self.chksum is None:
...             ck = checksum(p)
...             p = p[:2]+chr(ck>>8)+chr(ck&0xff)+p[4:]
...         return p
...
>>> bind_layers( IP, IGMP3, frag=0, proto=2)
>>> p = IP(dst="62.21.20.21")/IGMP3()
>>> send(p)
.
Sent 1 packets.
>>>

# tcpdump -ni cplane0 igmp -v
tcpdump: listening on cplane0, link-type EN10MB (Ethernet), capture size     262144 bytes
17:24:35.013987 IP (tos 0x0, ttl 62, id 1, offset 0, flags [none], proto IGMP (2), length 32)
44.60.11.3 > 62.21.20.21: igmp query v3 [max resp time 2.0s]
17:24:35.014000 IP (tos 0x0, ttl 62, id 1, offset 0, flags [none], proto IGMP (2), length 32)
44.60.11.3 > 62.21.20.21: igmp query v3 [max resp time 2.0s]
17:24:35.014476 IP (tos 0x0, ttl 62, id 1, offset 0, flags [none], proto IGMP (2), length 32)
44.60.11.3 > 62.21.20.21: igmp query v3 [max resp time 2.0s]
17:24:35.014482 IP (tos 0x0, ttl 62, id 1, offset 0, flags [none], proto IGMP (2), length 32)
44.60.11.3 > 62.21.20.21: igmp query v3 [max resp time 2.0s]
17:24:35.218208 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP (2), length 40, options (RA))
62.21.20.21 > 224.0.0.22: igmp v3 report, 1 group record(s) [gaddr 239.1.1.1 is_ex, 0 source(s)]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top