Commit ddf6baad authored by Pedro Oliveira's avatar Pedro Oliveira

Kernel and test JoinPrune

parent 48346dcf
...@@ -43,7 +43,7 @@ class Daemon: ...@@ -43,7 +43,7 @@ class Daemon:
sys.stderr.flush() sys.stderr.flush()
si = open(os.devnull, 'r') si = open(os.devnull, 'r')
so = open('stdout', 'a+') so = open('stdout', 'a+')
se = open(os.devnull, 'a+') se = open('stderror', 'a+')
os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(so.fileno(), sys.stdout.fileno())
......
...@@ -2,7 +2,7 @@ import random ...@@ -2,7 +2,7 @@ import random
from threading import Timer from threading import Timer
from Packet.Packet import Packet from Packet.Packet import Packet
from Packet.ReceivedPacket import ReceivedPacket from Packet.ReceivedPacket import ReceivedPacket
from Packet.PacketPimOption import PacketPimOption from Packet.PacketPimHello import PacketPimHello
from Packet.PacketPimHeader import PacketPimHeader from Packet.PacketPimHeader import PacketPimHeader
from Interface import Interface from Interface import Interface
import Main import Main
...@@ -28,9 +28,10 @@ class Hello: ...@@ -28,9 +28,10 @@ class Hello:
self.thread.start() self.thread.start()
def packet_send_handle(self, interface: Interface): def packet_send_handle(self, interface: Interface):
ph = PacketPimHeader(Hello.TYPE) pim_payload = PacketPimHello()
ph.add_option(PacketPimOption(1, Hello.TRIGGERED_HELLO_DELAY)) pim_payload.add_option(1, Hello.TRIGGERED_HELLO_DELAY)
ph.add_option(PacketPimOption(20, interface.generation_id)) pim_payload.add_option(20, interface.generation_id)
ph = PacketPimHeader(pim_payload)
packet = Packet(pim_header=ph) packet = Packet(pim_header=ph)
interface.send(packet.bytes()) interface.send(packet.bytes())
...@@ -42,9 +43,10 @@ class Hello: ...@@ -42,9 +43,10 @@ class Hello:
# TODO: ver melhor este metodo # TODO: ver melhor este metodo
def force_send_remove(self, interface: Interface): def force_send_remove(self, interface: Interface):
ph = PacketPimHeader(Hello.TYPE) pim_payload = PacketPimHello()
ph.add_option(PacketPimOption(1, KEEP_ALIVE_PERIOD_TIMEOUT)) pim_payload.add_option(1, KEEP_ALIVE_PERIOD_TIMEOUT)
ph.add_option(PacketPimOption(20, interface.generation_id)) pim_payload.add_option(20, interface.generation_id)
ph = PacketPimHeader(pim_payload)
packet = Packet(pim_header=ph) packet = Packet(pim_header=ph)
interface.send(packet.bytes()) interface.send(packet.bytes())
...@@ -55,7 +57,7 @@ class Hello: ...@@ -55,7 +57,7 @@ class Hello:
ip = packet.ip_header.ip ip = packet.ip_header.ip
print("ip = ", ip) print("ip = ", ip)
options = packet.pim_header.get_options() options = packet.pim_header.payload.get_options()
if Main.get_neighbor(ip) is None: if Main.get_neighbor(ip) is None:
# Unknown Neighbor # Unknown Neighbor
if (1 in options) and (20 in options): if (1 in options) and (20 in options):
......
...@@ -42,16 +42,17 @@ class Interface: ...@@ -42,16 +42,17 @@ class Interface:
while self.interface_enabled: while self.interface_enabled:
try: try:
(raw_packet, (ip, p)) = self.socket.recvfrom(256 * 1024) (raw_packet, (ip, p)) = self.socket.recvfrom(256 * 1024)
packet = ReceivedPacket(raw_packet, self) if raw_packet:
#print("packet received bytes: ", packet.bytes()) packet = ReceivedPacket(raw_packet, self)
#print("pim type received = ", packet.pim_header.msg_type) #print("packet received bytes: ", packet.bytes())
#print("generation id received = ", packet.pim_header.options[1].option_value) #print("pim type received = ", packet.pim_header.msg_type)
Main.protocols[packet.pim_header.msg_type].receive_handle(packet) # TODO: perceber se existe melhor maneira de fazer isto #print("options received = ", packet.pim_header.payload.options)
Main.protocols[packet.pim_header.get_pim_type()].receive_handle(packet) # TODO: perceber se existe melhor maneira de fazer isto
except Exception: except Exception:
pass pass
def send(self, data: bytes): def send(self, data: bytes):
if self.interface_enabled: if self.interface_enabled and data:
self.socket.sendto(data, (Interface.MCAST_GRP, 0)) self.socket.sendto(data, (Interface.MCAST_GRP, 0))
def remove(self): def remove(self):
......
import socket
import struct
import netifaces
import threading
class Kernel:
# MRT
MRT_BASE = 200
MRT_INIT = (MRT_BASE) # /* Activate the kernel mroute code */
MRT_DONE = (MRT_BASE + 1) # /* Shutdown the kernel mroute */
MRT_ADD_VIF = (MRT_BASE + 2) # /* Add a virtual interface */
MRT_DEL_VIF = (MRT_BASE + 3) # /* Delete a virtual interface */
MRT_ADD_MFC = (MRT_BASE + 4) # /* Add a multicast forwarding entry */
MRT_DEL_MFC = (MRT_BASE + 5) # /* Delete a multicast forwarding entry */
MRT_VERSION = (MRT_BASE + 6) # /* Get the kernel multicast version */
MRT_ASSERT = (MRT_BASE + 7) # /* Activate PIM assert mode */
MRT_PIM = (MRT_BASE + 8) # /* enable PIM code */
MRT_TABLE = (MRT_BASE + 9) # /* Specify mroute table ID */
#MRT_ADD_MFC_PROXY = (MRT_BASE + 10) # /* Add a (*,*|G) mfc entry */
#MRT_DEL_MFC_PROXY = (MRT_BASE + 11) # /* Del a (*,*|G) mfc entry */
#MRT_MAX = (MRT_BASE + 11)
# Max Number of Virtual Interfaces
MAXVIFS = 32
# SIGNAL MSG TYPE
IGMPMSG_NOCACHE = 1
IGMPMSG_WRONGVIF = 2
IGMPMSG_WHOLEPKT = 3
def __init__(self):
# Kernel is running
self.running = True
# KEY : interface_ip, VALUE : vif_index
self.vif_dic = {}
# KEY : (source_ip, group_ip), VALUE : ???? TODO
self.routing = {}
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IGMP)
# MRT INIT
s.setsockopt(socket.IPPROTO_IP, Kernel.MRT_INIT, 1)
# MRT PIM
s.setsockopt(socket.IPPROTO_IP, Kernel.MRT_PIM, 1)
self.socket = s
# Create virtual interfaces
interfaces = netifaces.interfaces()
for interface in interfaces:
#ignore localhost interface
if interface == 'lo':
continue
addrs = netifaces.ifaddresses(interface)
addr = addrs[netifaces.AF_INET][0]['addr']
try:
self.create_virtual_interface(addr)
except Exception:
continue
#self.set_multicast_route("10.2.2.2", "224.12.12.112", 0)
# TODO: background thread for receiving signals
# receive signals from kernel with a background thread
handler_thread = threading.Thread(target=self.handler)
handler_thread.daemon = True
handler_thread.start()
'''
Structure to create/remove virtual interfaces
struct vifctl {
vifi_t vifc_vifi; /* Index of VIF */
unsigned char vifc_flags; /* VIFF_ flags */
unsigned char vifc_threshold; /* ttl limit */
unsigned int vifc_rate_limit; /* Rate limiter values (NI) */
union {
struct in_addr vifc_lcl_addr; /* Local interface address */
int vifc_lcl_ifindex; /* Local interface index */
};
struct in_addr vifc_rmt_addr; /* IPIP tunnel addr */
};
'''
def create_virtual_interface(self, ip_interface, index=None, flags=0x0):
if (type(ip_interface) is not bytes) and (type(ip_interface) is not str):
raise Exception
elif type(ip_interface) is str:
ip_interface = socket.inet_aton(ip_interface)
if index is None:
index = len(self.vif_dic)
struct_mrt_add_vif = struct.pack("HBBI 4s 4s", index, flags, 1, 0, ip_interface, socket.inet_aton("0.0.0.0"))
self.socket.setsockopt(socket.IPPROTO_IP, Kernel.MRT_ADD_VIF, struct_mrt_add_vif)
self.vif_dic[socket.inet_ntoa(ip_interface)] = index
def remove_virtual_interface(self, ip_interface):
index = self.vif_dic[ip_interface]
return
'''
/* Cache manipulation structures for mrouted and PIMd */
struct mfcctl {
struct in_addr mfcc_origin; /* Origin of mcast */
struct in_addr mfcc_mcastgrp; /* Group in question */
vifi_t mfcc_parent; /* Where it arrived */
unsigned char mfcc_ttls[MAXVIFS]; /* Where it is going */
unsigned int mfcc_pkt_cnt; /* pkt count for src-grp */
unsigned int mfcc_byte_cnt;
unsigned int mfcc_wrong_if;
int mfcc_expire;
};
'''
def set_multicast_route(self, source_ip, group_ip, inbound_interface_index, outbound_interfaces=None):
if (type(source_ip) not in (bytes, str)) or (type(group_ip) not in (bytes, str)):
raise Exception
if type(source_ip) is str:
source_ip = socket.inet_aton(source_ip)
if type(group_ip) is str:
group_ip = socket.inet_aton(group_ip)
if outbound_interfaces is None:
outbound_interfaces = [1]*Kernel.MAXVIFS
outbound_interfaces[inbound_interface_index] = 0
elif len(outbound_interfaces) != Kernel.MAXVIFS:
raise Exception
outbound_interfaces_and_other_parameters = list(outbound_interfaces) + [0]*4
#outbound_interfaces, 0, 0, 0, 0 <- only works with python>=3.5
#struct_mfcctl = struct.pack("4s 4s H " + "B"*Kernel.MAXVIFS + " IIIi", source_ip, group_ip, inbound_interface_index, *outbound_interfaces, 0, 0, 0, 0)
struct_mfcctl = struct.pack("4s 4s H " + "B"*Kernel.MAXVIFS + " IIIi", source_ip, group_ip, inbound_interface_index, *outbound_interfaces_and_other_parameters)
self.socket.setsockopt(socket.IPPROTO_IP, Kernel.MRT_ADD_MFC, struct_mfcctl)
# TODO: ver melhor tabela routing
self.routing[(socket.inet_ntoa(source_ip), socket.inet_ntoa(group_ip))] = {"inbound_interface_index":inbound_interface_index, "outbound_interfaces": outbound_interfaces}
def remove_multicast_route(self):
return
def exit(self):
self.running = False
# MRT DONE
self.socket.setsockopt(socket.IPPROTO_IP, Kernel.MRT_DONE, 1)
self.socket.close()
'''
/* This is the format the mroute daemon expects to see IGMP control
* data. Magically happens to be like an IP packet as per the original
*/
struct igmpmsg {
__u32 unused1,unused2;
unsigned char im_msgtype; /* What is this */
unsigned char im_mbz; /* Must be zero */
unsigned char im_vif; /* Interface (this ought to be a vifi_t!) */
unsigned char unused3;
struct in_addr im_src,im_dst;
};
'''
def handler(self):
while self.running:
try:
msg = self.socket.recv(5000)
print(len(msg))
(_, _, im_msgtype, im_mbz, im_vif, _, im_src, im_dst, _) = struct.unpack("II B B B B 4s 4s 8s", msg)
print(im_msgtype)
print(im_mbz)
print(im_vif)
print(socket.inet_ntoa(im_src))
print(socket.inet_ntoa(im_dst))
print(struct.unpack("II B B B B 4s 4s 8s", msg))
if im_mbz != 0:
continue
if im_msgtype == Kernel.IGMPMSG_NOCACHE:
print("IGMP NO CACHE")
self.set_multicast_route(im_src, im_dst, im_vif)
# TODO: handler
except Exception:
continue
import netifaces import netifaces
from prettytable import PrettyTable from prettytable import PrettyTable
from Interface import Interface from Interface import Interface
from Neighbor import Neighbor from Neighbor import Neighbor
interfaces = {} # interfaces with multicast routing enabled interfaces = {} # interfaces with multicast routing enabled
neighbors = {} # multicast router neighbors neighbors = {} # multicast router neighbors
protocols = {} protocols = {}
...@@ -67,6 +67,20 @@ def list_neighbors(): ...@@ -67,6 +67,20 @@ def list_neighbors():
def list_enabled_interfaces(): def list_enabled_interfaces():
global interfaces global interfaces
for interface in interfaces:
from Packet.Packet import Packet
from Packet.PacketPimHeader import PacketPimHeader
from Packet.PacketPimJoinPrune import PacketPimJoinPrune
from Packet.PacketPimJoinPruneMulticastGroup import PacketPimJoinPruneMulticastGroup
ph = PacketPimJoinPrune(167772173, 20)
ph.add_multicast_group(PacketPimJoinPruneMulticastGroup(3708422657, [3708422657], []))
pckt = Packet(pim_header=PacketPimHeader(ph))
interfaces[interface].send(pckt.bytes())
t = PrettyTable(['Interface', 'IP', 'Enabled']) t = PrettyTable(['Interface', 'IP', 'Enabled'])
for interface in netifaces.interfaces(): for interface in netifaces.interfaces():
# TODO: fix same interface with multiple ips # TODO: fix same interface with multiple ips
......
from Packet.PacketIpHeader import PacketIpHeader from Packet.PacketIpHeader import PacketIpHeader
from Packet.PacketPimHeader import PacketPimHeader from Packet.PacketPimHeader import PacketPimHeader
from Packet.PacketPimOption import PacketPimOption
class Packet: class Packet:
......
import struct import struct
from utils import checksum from utils import checksum
from Packet.PacketPimOption import PacketPimOption
class PacketPimHeader: class PacketPimHeader:
...@@ -9,35 +8,18 @@ class PacketPimHeader: ...@@ -9,35 +8,18 @@ class PacketPimHeader:
PIM_HDR = "! BB H" PIM_HDR = "! BB H"
PIM_HDR_LEN = struct.calcsize(PIM_HDR) PIM_HDR_LEN = struct.calcsize(PIM_HDR)
# HELLO: type = 0 def __init__(self, payload):
# pim options self.payload = payload
def __init__(self, msg_type: int): #self.msg_type = msg_type
self.options = []
self.msg_type = msg_type
def add_option(self, option: PacketPimOption): def get_pim_type(self):
self.options.append(option) return self.payload.PIM_TYPE
def get_options_bytes(self):
res = b''
#print(self.options[0].option_type)
self.options.sort(key=lambda x: x.option_type) # TODO: duvida... ordenar? maybe not
#print(self.options[0].option_type)
for opt in self.options:
res += opt.bytes()
return res
def get_options(self):
dictionary = {}
for option in self.options:
dictionary[option.option_type] = option.option_value
return dictionary
def bytes(self) -> bytes: def bytes(self) -> bytes:
# obter mensagem e criar checksum # obter mensagem e criar checksum
pim_vrs_type = (PacketPimHeader.PIM_VERSION << 4) + self.msg_type pim_vrs_type = (PacketPimHeader.PIM_VERSION << 4) + self.get_pim_type()
msg_without_chcksum = struct.pack(PacketPimHeader.PIM_HDR, pim_vrs_type, 0, 0) msg_without_chcksum = struct.pack(PacketPimHeader.PIM_HDR, pim_vrs_type, 0, 0)
msg_without_chcksum += self.get_options_bytes() msg_without_chcksum += self.payload.bytes()
pim_checksum = checksum(msg_without_chcksum) pim_checksum = checksum(msg_without_chcksum)
msg = msg_without_chcksum[0:2] + struct.pack("! H", pim_checksum) + msg_without_chcksum[4:] msg = msg_without_chcksum[0:2] + struct.pack("! H", pim_checksum) + msg_without_chcksum[4:]
return msg return msg
...@@ -25,7 +25,7 @@ class PacketPimHello: ...@@ -25,7 +25,7 @@ class PacketPimHello:
def bytes(self) -> bytes: def bytes(self) -> bytes:
res = b'' res = b''
for (option_type, option_value) in self.options.items(): for (option_type, option_value) in self.options.items():
option_length = self.PIM_MSG_TYPES_LENGTH[option_type] option_length = PacketPimHello.PIM_MSG_TYPES_LENGTH[option_type]
type_length_hdr = struct.pack(self.PIM_HDR_OPTS, option_type, option_length) type_length_hdr = struct.pack(PacketPimHello.PIM_HDR_OPTS, option_type, option_length)
res += type_length_hdr + struct.pack("! " + str(option_length) + "s", option_value.to_bytes(option_length, byteorder='big')) res += type_length_hdr + struct.pack("! " + str(option_length) + "s", option_value.to_bytes(option_length, byteorder='big'))
return res return res
...@@ -2,7 +2,8 @@ import struct ...@@ -2,7 +2,8 @@ import struct
class PacketPimJoinPrune: class PacketPimJoinPrune:
PIM_HDR_JOIN_PRUNE = "! 4S BBH " PIM_TYPE = 3
PIM_HDR_JOIN_PRUNE = "! 4s BBH "
PIM_HDR_JOIN_PRUNE_LEN = struct.calcsize(PIM_HDR_JOIN_PRUNE) PIM_HDR_JOIN_PRUNE_LEN = struct.calcsize(PIM_HDR_JOIN_PRUNE)
def __init__(self, upstream_neighbor_address, hold_time): def __init__(self, upstream_neighbor_address, hold_time):
...@@ -15,7 +16,8 @@ class PacketPimJoinPrune: ...@@ -15,7 +16,8 @@ class PacketPimJoinPrune:
self.groups.append(group) self.groups.append(group)
def bytes(self) -> bytes: def bytes(self) -> bytes:
msg = struct.pack(self.PIM_HDR_JOIN_PRUNE, self.upstream_neighbor_address, 0, len(self.groups), self.hold_time) # TODO esta a converter upstream neighbor (considera que recebe int) para bytes
msg = struct.pack(PacketPimJoinPrune.PIM_HDR_JOIN_PRUNE, self.upstream_neighbor_address.to_bytes(4, byteorder='big'), 0, len(self.groups), self.hold_time)
for multicast_group in self.groups: for multicast_group in self.groups:
msg += multicast_group.bytes() msg += multicast_group.bytes()
......
...@@ -16,12 +16,12 @@ class PacketPimJoinPruneMulticastGroup: ...@@ -16,12 +16,12 @@ class PacketPimJoinPruneMulticastGroup:
def bytes(self) -> bytes: def bytes(self) -> bytes:
# TODO: verificar multicast_group # TODO: verificar multicast_group
msg = struct.pack(self.PIM_HDR_JOIN_PRUNE_MULTICAST_GROUP, self.multicast_group, len(self.joined_src_addresses), len(self.pruned_src_addresses)) msg = struct.pack(self.PIM_HDR_JOIN_PRUNE_MULTICAST_GROUP, self.multicast_group.to_bytes(4, byteorder='big'), len(self.joined_src_addresses), len(self.pruned_src_addresses))
for joined_src_address in self.joined_src_addresses: for joined_src_address in self.joined_src_addresses:
msg = struct.pack(self.PIM_HDR_JOINED_PRUNED_SOURCE, joined_src_address) msg += struct.pack(self.PIM_HDR_JOINED_PRUNED_SOURCE, joined_src_address.to_bytes(4, byteorder='big'))
for pruned_src_address in self.pruned_src_addresses: for pruned_src_address in self.pruned_src_addresses:
msg = struct.pack(self.PIM_HDR_JOINED_PRUNED_SOURCE, pruned_src_address) msg += struct.pack(self.PIM_HDR_JOINED_PRUNED_SOURCE, pruned_src_address.to_bytes(4, byteorder='big'))
# TODO: verificar pruned e joined addrss # TODO: verificar pruned e joined addrss
return msg return msg
import struct
class PacketPimOption:
PIM_HDR_OPTS = "! HH"
PIM_HDR_OPTS_LEN = struct.calcsize(PIM_HDR_OPTS)
PIM_MSG_TYPES_LENGTH = {1: 2,
20: 4,
}
def __init__(self, option_type: int, option_value: int):
self.option_type = option_type
self.option_value = option_value
def bytes(self) -> bytes:
option_length = PacketPimOption.PIM_MSG_TYPES_LENGTH[self.option_type]
msg = struct.pack(PacketPimOption.PIM_HDR_OPTS, self.option_type, option_length)
return msg + struct.pack("! " + str(option_length) + "s", self.option_value.to_bytes(option_length, byteorder='big'))
...@@ -2,14 +2,17 @@ import struct ...@@ -2,14 +2,17 @@ import struct
from Packet.Packet import Packet from Packet.Packet import Packet
from Packet.PacketIpHeader import PacketIpHeader from Packet.PacketIpHeader import PacketIpHeader
from Packet.PacketPimHeader import PacketPimHeader from Packet.PacketPimHeader import PacketPimHeader
from Packet.PacketPimOption import PacketPimOption from Packet.PacketPimHello import PacketPimHello
from Packet.PacketPimJoinPrune import PacketPimJoinPrune
from Packet.PacketPimJoinPruneMulticastGroup import PacketPimJoinPruneMulticastGroup
from utils import checksum from utils import checksum
class ReceivedPacket(Packet): class ReceivedPacket(Packet):
def __init__(self, raw_packet, interface): def __init__(self, raw_packet, interface):
self.interface = interface self.interface = interface
#Parse ao packet e preencher objeto Packet # Parse ao packet e preencher objeto Packet
x = ReceivedPacket.parseIpHdr(raw_packet[:PacketIpHeader.IP_HDR_LEN]) x = ReceivedPacket.parseIpHdr(raw_packet[:PacketIpHeader.IP_HDR_LEN])
print(x["HLEN"]) print(x["HLEN"])
...@@ -24,12 +27,16 @@ class ReceivedPacket(Packet): ...@@ -24,12 +27,16 @@ class ReceivedPacket(Packet):
print("wrong checksum") print("wrong checksum")
return # TODO: maybe excepcao return # TODO: maybe excepcao
print(pim_hdr) print(pim_hdr)
self.pim_header = PacketPimHeader(pim_hdr["TYPE"]) pim_payload = None
if pim_hdr["TYPE"] == 0: # hello if pim_hdr["TYPE"] == 0: # hello
pim_options = ReceivedPacket.parsePimHdrOpts(msg_without_ip_hdr[PacketPimHeader.PIM_HDR_LEN:]) pim_payload = PacketPimHello()
pim_options = ReceivedPacket.parsePimHelloOpts(msg_without_ip_hdr[PacketPimHeader.PIM_HDR_LEN:])
print(pim_options) print(pim_options)
for option in pim_options: for option in pim_options:
self.pim_header.add_option(PacketPimOption(option["OPTION TYPE"], option["OPTION VALUE"])) pim_payload.add_option(option["OPTION TYPE"], option["OPTION VALUE"])
elif pim_hdr["TYPE"] == 3: # join/prune
pim_payload = PacketPimJoinPrune()
self.pim_header = PacketPimHeader(pim_payload)
print(self.bytes()) print(self.bytes())
def parseIpHdr(msg): def parseIpHdr(msg):
...@@ -53,7 +60,7 @@ class ReceivedPacket(Packet): ...@@ -53,7 +60,7 @@ class ReceivedPacket(Packet):
} }
def parsePimHdr(msg): def parsePimHdr(msg):
#print("parsePimHdr: ", msg.encode("hex")) # print("parsePimHdr: ", msg.encode("hex"))
print("parsePimHdr: ", msg) print("parsePimHdr: ", msg)
(pim_ver_type, reserved, checksum) = struct.unpack(PacketPimHeader.PIM_HDR, msg) (pim_ver_type, reserved, checksum) = struct.unpack(PacketPimHeader.PIM_HDR, msg)
...@@ -64,13 +71,14 @@ class ReceivedPacket(Packet): ...@@ -64,13 +71,14 @@ class ReceivedPacket(Packet):
"CHECKSUM": checksum "CHECKSUM": checksum
} }
def parsePimHdrOpts(msg): def parsePimHelloOpts(msg):
options_list = [] options_list = []
# print(msg) # print(msg)
while msg != b'': while msg != b'':
(option_type, option_length) = struct.unpack(PacketPimOption.PIM_HDR_OPTS, msg[:PacketPimOption.PIM_HDR_OPTS_LEN]) (option_type, option_length) = struct.unpack(PacketPimHello.PIM_HDR_OPTS,
msg[:PacketPimHello.PIM_HDR_OPTS_LEN])
print(option_type, option_length) print(option_type, option_length)
msg = msg[PacketPimOption.PIM_HDR_OPTS_LEN:] msg = msg[PacketPimHello.PIM_HDR_OPTS_LEN:]
print(msg) print(msg)
(option_value,) = struct.unpack("! " + str(option_length) + "s", msg[:option_length]) (option_value,) = struct.unpack("! " + str(option_length) + "s", msg[:option_length])
option_value_number = int.from_bytes(option_value, byteorder='big') option_value_number = int.from_bytes(option_value, byteorder='big')
...@@ -81,3 +89,36 @@ class ReceivedPacket(Packet): ...@@ -81,3 +89,36 @@ class ReceivedPacket(Packet):
}) })
msg = msg[option_length:] msg = msg[option_length:]
return options_list return options_list
def parsePimJoinPrune(msg):
(upstream_neighbor, reserved, num_groups, hold_time) = struct.unpack(PacketPimJoinPrune.PIM_HDR_JOIN_PRUNE,
msg[
:PacketPimJoinPrune.PIM_HDR_JOIN_PRUNE_LEN])
msg = msg[PacketPimJoinPrune.PIM_HDR_JOIN_PRUNE_LEN:]
options_list = []
# print(msg)
while msg != b'':
(multicast_group, num_joins, num_prunes) = struct.unpack(
PacketPimJoinPruneMulticastGroup.PIM_HDR_JOIN_PRUNE_MULTICAST_GROUP,
msg[:PacketPimJoinPruneMulticastGroup.PIM_HDR_JOIN_PRUNE_MULTICAST_GROUP_LEN])
msg = msg[PacketPimJoinPruneMulticastGroup.PIM_HDR_JOIN_PRUNE_MULTICAST_GROUP_LEN:]
joined = []
pruned = []
for i in range(0, num_joins):
(joined_addr) = struct.unpack(
PacketPimJoinPruneMulticastGroup.PIM_HDR_JOINED_PRUNED_SOURCE,
msg[:PacketPimJoinPruneMulticastGroup.PIM_HDR_JOINED_PRUNED_SOURCE_LEN])
msg = msg[PacketPimJoinPruneMulticastGroup.PIM_HDR_JOINED_PRUNED_SOURCE_LEN:]
joined.append(joined_addr)
for i in range(0, num_prunes):
(pruned_addr) = struct.unpack(
PacketPimJoinPruneMulticastGroup.PIM_HDR_JOINED_PRUNED_SOURCE,
msg[:PacketPimJoinPruneMulticastGroup.PIM_HDR_JOINED_PRUNED_SOURCE_LEN])
msg = msg[PacketPimJoinPruneMulticastGroup.PIM_HDR_JOINED_PRUNED_SOURCE_LEN:]
pruned.append(pruned_addr)
packet_join_prune_groups = PacketPimJoinPruneMulticastGroup(multicast_group, joined, pruned)
options_list.append(packet_join_prune_groups) # TODO: ver melhor
print(options_list)
return options_list
import socket
import time
import struct
# ficheiros importantes: /usr/include/linux/mroute.h
MRT_BASE = 200
MRT_INIT = (MRT_BASE) # Activate the kernel mroute code */
MRT_DONE = (MRT_BASE+1) #/* Shutdown the kernel mroute */
MRT_ADD_VIF = (MRT_BASE+2) #/* Add a virtual interface */
MRT_DEL_VIF = (MRT_BASE+3) #/* Delete a virtual interface */
MRT_ADD_MFC = (MRT_BASE+4) #/* Add a multicast forwarding entry */
MRT_DEL_MFC = (MRT_BASE+5) #/* Delete a multicast forwarding entry */
MRT_VERSION = (MRT_BASE+6) #/* Get the kernel multicast version */
MRT_ASSERT = (MRT_BASE+7) #/* Activate PIM assert mode */
MRT_PIM = (MRT_BASE+8) #/* enable PIM code */
MRT_TABLE = (MRT_BASE+9) #/* Specify mroute table ID */
MRT_ADD_MFC_PROXY = (MRT_BASE+10) #/* Add a (*,*|G) mfc entry */
MRT_DEL_MFC_PROXY = (MRT_BASE+11) #/* Del a (*,*|G) mfc entry */
MRT_MAX = (MRT_BASE+11)
IGMPMSG_NOCACHE = 1
IGMPMSG_WRONGVIF = 2
IGMPMSG_WHOLEPKT = 3
s2 = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IGMP)
#MRT INIT
s2.setsockopt(socket.IPPROTO_IP, MRT_INIT, 1)
#MRT PIM
s2.setsockopt(socket.IPPROTO_IP, MRT_PIM, 1)
#ADD VIRTUAL INTERFACE
#estrutura = struct.pack("HBBI 4s 4s", 1, 0x4, 0, 0, socket.inet_aton("192.168.1.112"), socket.inet_aton("224.1.1.112"))
estrutura = struct.pack("HBBI 4s 4s", 0, 0x0, 1, 0, socket.inet_aton("10.0.0.1"), socket.inet_aton("0.0.0.0"))
print(estrutura)
s2.setsockopt(socket.IPPROTO_IP, MRT_ADD_VIF, estrutura)
estrutura = struct.pack("HBBI 4s 4s", 1, 0x0, 1, 0, socket.inet_aton("192.168.2.2"), socket.inet_aton("0.0.0.0"))
print(estrutura)
s2.setsockopt(socket.IPPROTO_IP, MRT_ADD_VIF, estrutura)
#time.sleep(5)
while True:
print("recv:")
msg = s2.recv(5000)
print(len(msg))
(_, _, im_msgtype, im_mbz, im_vif, _, im_src, im_dst, _) = struct.unpack("II B B B B 4s 4s 8s", msg)
print(im_msgtype)
print(im_mbz)
print(im_vif)
print(socket.inet_ntoa(im_src))
print(socket.inet_ntoa(im_dst))
if im_msgtype == IGMPMSG_NOCACHE:
print("^^ IGMP NO CACHE")
print(struct.unpack("II B B B B 4s 4s 8s", msg))
#s2.setsockopt(socket.IPPROTO_IP, MRT_PIM, 1)
#print(s2.getsockopt(socket.IPPROTO_IP, 208))
#s2.setsockopt(socket.IPPROTO_IP, 208, 0)
#ADD MULTICAST FORWARDING ENTRY
estrutura = struct.pack("4s 4s H BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB IIIi", socket.inet_aton("10.0.0.2"), socket.inet_aton("224.1.1.113"), 0, 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0)
s2.setsockopt(socket.IPPROTO_IP, MRT_ADD_MFC, estrutura)
time.sleep(30)
#MRT DONE
s2.setsockopt(socket.IPPROTO_IP, MRT_DONE, 1)
s2.close()
exit(1)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment