Good afternoon everyone,
my coding skills are not quite on the level required to do socket programming myself and I was wondering if someone here can help me with what I need - which is fairly simple:
I want to send a "dummy" PIM join packets to a neighbouring device without really bothering maintaining any PIM adjacencies/(hellos). Ideally I want to end-up with a function that accepts a few arguments:
def send_dummy_join(group, rp, source_ip):
// send 1 join every time this function is called
Ideally I need it to run using python3 not using external modules (e.g. scapy)
Another problem I have & don't quite understand how to solve is crafting a packet with a source address which doesn't belong to any network interface on the system. I know scapy can do this I only don't quite understand how to craft it myself.
Thanks in advance for all your help. Much appreciated!
Some external information.
http://www.networksorcery.com/enp/protocol/pim.htm
I will most probably (fully rightfully though ;-)) get publicly lynched for the following piece of code, but as one network engineer to another check out the code below.
A few more bits to bear in mind - You need to "establish adjacency" first (exchange some hello packets) or your PIM joins will get ignored by the upstream router (hence the dummy hello function added).
Furthermore, the "Upstream Neighbour IP" is also necessary when sending PIM joins.
import socket
from struct import pack, iter_unpack
from functools import reduce
def checksum(data):
sum = reduce(lambda x, y: x + y, iter_unpack("!H",data))
s = reduce(lambda x, y: x + y, sum)
while (s >> 16):
s = (s & 0xFFFF) + (s >> 16)
s = ~s & 0xffff
return s
def send_dummy_hello():
PIM_GROUP = '224.0.0.13'
sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_PIM)
my_packet=pack('!BBH3H4H4H4H', 32, 0, 24707, 1, 2, 105, 20, 4, 16121,
16078, 19, 4, 0, 1, 21, 4, 256, 0)
sock.sendto(my_packet, (PIM_GROUP,0))
def send_dummy_join(group, rp_addr, neighbor_ip):
PIM_GROUP = '224.0.0.13'
sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_PIM)
pim_ver = 35
pim_res = 0
pktchksum = 0
pim_opts = 256
neighbor = socket.inet_aton(neighbor_ip)
ngroups = 1
holdtime = 210
subnet = socket.inet_aton('1.0.0.32')
group_a = socket.inet_aton(group)
num_joins = 1
num_prunes = 0
rrp_subnet = socket.inet_aton('1.0.7.32')
rp_address = socket.inet_aton(rp_addr)
my_packet = pack('!BB2H4sHH4s4sHH4s4s', pim_ver, pim_res, pktchksum, pim_opts,
neighbor, ngroups, holdtime, subnet, group_a, num_joins, num_prunes,
rrp_subnet, rp_address)
pktchksum = checksum(my_packet)
my_packet = pack('!BB2H4sHH4s4sHH4s4s', pim_ver, pim_res, pktchksum, pim_opts,
neighbor, ngroups, holdtime, subnet, group_a, num_joins, num_prunes,
rrp_subnet, rp_address)
sock.sendto(my_packet, (PIM_GROUP,0))
print (f'PIM Join sent to {neighbor_ip} for {group} & RP {rp_addr}')
>>>send_dummy_hello()
>>>send_dummy_join('239.10.20.30','192.168.0.1','10.0.0.102')
I tested this with EVE-NG and it (magically!) worked :-)
EDIT:
The code is now edited to support header checksum calculation. I think this is now complete! :-)