Example how to access raw socket in Python:
#!/usr/bin/python
from socket import *
from struct import *
from time import *
import sys
import IN
import threading
import signal
src = '192.168.2.2'
dst = '224.0.0.1'
dev = "eth1.100" + "\0"
if len(sys.argv) > 1:
dev = sys.argv[1]
print "device = %s" % dev
src = gethostbyname(gethostname())
def ichecksum(data, sum=0):
""" Compute the Internet Checksum of the supplied data. The checksum is
initialized to zero. Place the return value in the checksum field of a
packet. When the packet is received, check the checksum, by passing
in the checksum field of the packet and the data. If the result is zero,
then the checksum has not detected an error.
"""
# make 16 bit words out of every two adjacent 8 bit words in the packet
# and add them up
for i in range(0,len(data),2):
if i + 1 >= len(data):
sum += ord(data[i]) & 0xFF
else:
w = ((ord(data[i]) <> 16) > 0)
sum = (sum & 0xFFFF) + (sum >> 16)
# one's complement the result
sum = ~sum
return sum & 0xFFFF
def dump( data ):
i = 0
for x in data:
if i == 4:
print ''
i = 0
i += 1
sys.stdout.write( ' %0.2x' % ord(x) )
print ''
# ip header generation
def create_ip_hdr(id, type):
ip_ihl = 5
ip_ver = 4
ip_tos = 0
ip_tot_len = 0 # kernel will fill the correct total length
ip_frag_off = 0
ip_ttl = 255
ip_proto = type #IPPROTO_IGMP
ip_check = 0 # kernel will fill the correct checksum
isrc = inet_aton( src )
idst = inet_aton( dst )
ip_ihl_ver = (ip_ver << 4) + ip_ihl
router_alert = int( '1001010000000100', 2 ) << 16
# the ! in the pack format string means network order
ip_hdr = pack('!BBHHHBBH4s4sI',
ip_ihl_ver, ip_tos, ip_tot_len, id, ip_frag_off, ip_ttl, ip_proto,
ip_check,
isrc, idst,
router_alert)
crc = pack( '!H', ichecksum( ip_hdr ) )
ip_hdr = ip_hdr[:10] + crc + ip_hdr[12:]
return ip_hdr
# IGMP header:
# type (octet), max resp time (octet), checksum (octet), group (4-octets)
IGMP_QUERY = 0x11
IGMP_REPORT = 0x16
IGMP_LEAVE = 0x17
igmp_type = IGMP_QUERY
IGMP_RESP_TIME = 120
def create_igmp_packet(id, type, group_addr='224.0.0.1'):
igmp = pack( '!BBH4s', type, IGMP_RESP_TIME, 0, inet_aton(group_addr))
crc = pack( '!H', ichecksum( igmp ) )
igmp = igmp[0:2] + crc + igmp[4:]
packet = create_ip_hdr(id, IPPROTO_IGMP) + igmp
print 'packet:'
dump( packet )
return packet
def create_non_igmp_packet(id, type, group_addr='224.0.0.1'):
igmp = pack( '!BBH4s', type, IGMP_RESP_TIME, 0, inet_aton(group_addr))
crc = pack( '!H', ichecksum( igmp ) )
igmp = igmp[0:2] + crc + igmp[4:]
packet = create_ip_hdr(id, IPPROTO_UDP) + igmp
print 'packet:'
dump( packet )
return packet
group = '224.0.0.1'
id = 1
s = socket( AF_INET, SOCK_RAW, IPPROTO_RAW )
s.setsockopt( IPPROTO_IP, IP_HDRINCL, 1 )
s.setsockopt( IPPROTO_IP, IP_MULTICAST_TTL, 2)
s.setsockopt( SOL_SOCKET, IN.SO_BINDTODEVICE, dev)
socksema = threading.Semaphore()
stop = False
def signal_handler(signal, frame):
global stop
print 'You pressed Ctrl+C!'
stop = True
#th1.join()
#th2.join()
#sys.exit(0)
class IgmpQueryThread(threading.Thread):
def run(self):
global stop,id
while (not stop):
socksema.acquire()
print "Sending IGMP query"
igmp_q = create_igmp_packet(id, IGMP_QUERY, group)
print s.sendto( igmp_q, (dst, 0) )
socksema.release()
dump( igmp_q)
id += 1
sleep(1)
class IgmpReportThread(threading.Thread):
def run(self):
global stop,id
while (not stop):
socksema.acquire()
print "Sending IGMP report"
igmp_r = create_igmp_packet(id, IGMP_REPORT, group)
print s.sendto( igmp_r, (dst, 0) )
id += 1
socksema.release()
sleep(1)
i = 0
th1 = IgmpQueryThread()
th2 = IgmpReportThread()
th1.start()
th2.start()
signal.signal(signal.SIGINT, signal_handler)
print 'Press Ctrl+C to quit'
#signal.pause()
while(not stop):
if (i % 5 == 0):
print "Sending NON-IGMP (%d)" % i
false_igmp = create_non_igmp_packet(id, IGMP_QUERY, group)
print s.sendto( false_igmp, (dst, 0) )
#stop = True
id += 1
sleep( 1 )
i += 1
th1.join()
th2.join()
s.close()