Commit f3d3c0ef authored by Pedro Oliveira's avatar Pedro Oliveira

parse join/prune

parent 4bfb18c6
......@@ -55,7 +55,7 @@ class Hello:
if packet.ip_header is None:
return # TODO: MAYBE EXCEPCAO??
ip = packet.ip_header.ip
ip = packet.ip_header.ip_src
print("ip = ", ip)
options = packet.pim_header.payload.get_options()
if Main.get_neighbor(ip) is None:
......
......@@ -4,6 +4,7 @@ import random
import netifaces
from Packet.ReceivedPacket import ReceivedPacket
import Main
import traceback
class Interface:
MCAST_GRP = '224.0.0.13'
......@@ -51,7 +52,8 @@ class Interface:
#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:
pass
traceback.print_exc()
continue
def send(self, data: bytes):
if self.interface_enabled and data:
......
import struct
import socket
'''
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
'''
class PacketIpHeader:
IP_HDR = "! BBH HH BBH 4s 4s"
#IP_HDR2 = "! B"
IP_HDR_LEN = struct.calcsize(IP_HDR)
def __init__(self, ip):
self.ip = ip
def __init__(self, ver, hdr_len, ttl, proto, ip_src, ip_dst):
self.version = ver
self.hdr_length = hdr_len
self.ttl = ttl
self.proto = proto
self.ip_src = ip_src
self.ip_dst = ip_dst
@staticmethod
def parse_bytes(data: bytes):
(verhlen, tos, iplen, ipid, frag, ttl, proto, cksum, src, dst) = \
struct.unpack(PacketIpHeader.IP_HDR, data)
ver = (verhlen & 0xf0) >> 4
hlen = (verhlen & 0x0f) * 4
'''
"VER": ver,
"HLEN": hlen,
"TOS": tos,
"IPLEN": iplen,
"IPID": ipid,
"FRAG": frag,
"TTL": ttl,
"PROTO": proto,
"CKSUM": cksum,
"SRC": socket.inet_ntoa(src),
"DST": socket.inet_ntoa(dst)
'''
src_ip = socket.inet_ntoa(src)
dst_ip = socket.inet_ntoa(dst)
return PacketIpHeader(ver, hlen, ttl, proto, src_ip, dst_ip)
......@@ -18,6 +18,7 @@ class PacketPimEncodedGroupAddress:
IPV6_HDR = "16s"
# TODO ver melhor versao ip
PIM_ENCODED_GROUP_ADDRESS_HDR_WITHOUT_GROUP_ADDRESS_LEN = struct.calcsize(PIM_ENCODED_GROUP_ADDRESS_HDR_WITHOUT_GROUP_MULTICAST_ADDRESS)
PIM_ENCODED_GROUP_ADDRESS_HDR_LEN = struct.calcsize(PIM_ENCODED_GROUP_ADDRESS_HDR % IPV4_HDR)
PIM_ENCODED_GROUP_ADDRESS_HDR_LEN_IPv6 = struct.calcsize(PIM_ENCODED_GROUP_ADDRESS_HDR % IPV6_HDR)
......@@ -37,7 +38,8 @@ class PacketPimEncodedGroupAddress:
def bytes(self) -> bytes:
(string_ip_hdr, hdr_addr_family, socket_family) = PacketPimEncodedGroupAddress.get_ip_info(self.group_address)
if self.mask_len is None:
mask_len = self.mask_len
if mask_len is None:
mask_len = 8 * struct.calcsize(string_ip_hdr)
ip = socket.inet_pton(socket_family, self.group_address)
......@@ -54,3 +56,23 @@ class PacketPimEncodedGroupAddress:
return (PacketPimEncodedGroupAddress.IPV6_HDR, PacketPimEncodedGroupAddress.FAMILY_IPV6, socket.AF_INET6)
else:
raise Exception
@staticmethod
def parse_bytes(data: bytes):
data_without_group_addr = data[0:PacketPimEncodedGroupAddress.PIM_ENCODED_GROUP_ADDRESS_HDR_WITHOUT_GROUP_ADDRESS_LEN]
(addr_family, encoding, _, mask_len) = struct.unpack(PacketPimEncodedGroupAddress.PIM_ENCODED_GROUP_ADDRESS_HDR_WITHOUT_GROUP_MULTICAST_ADDRESS, data_without_group_addr)
data_group_addr = data[PacketPimEncodedGroupAddress.PIM_ENCODED_GROUP_ADDRESS_HDR_WITHOUT_GROUP_ADDRESS_LEN:]
ip = None
if addr_family == PacketPimEncodedGroupAddress.FAMILY_IPV4:
(ip,) = struct.unpack("! " + PacketPimEncodedGroupAddress.IPV4_HDR, data_group_addr[:4])
ip = socket.inet_ntop(socket.AF_INET, ip)
elif addr_family == PacketPimEncodedGroupAddress.FAMILY_IPV6:
(ip,) = struct.unpack("! " + PacketPimEncodedGroupAddress.IPV6_HDR, data_group_addr[:16])
ip = socket.inet_ntop(socket.AF_INET6, ip)
if encoding != 0:
print("unknown encoding")
raise Exception
return PacketPimEncodedGroupAddress(ip, mask_len)
......@@ -19,6 +19,7 @@ class PacketPimEncodedSourceAddress:
IPV6_HDR = "16s"
# TODO ver melhor versao ip
PIM_ENCODED_SOURCE_ADDRESS_HDR_WITHOUT_SOURCE_ADDRESS_LEN = struct.calcsize(PIM_ENCODED_SOURCE_ADDRESS_HDR_WITHOUT_SOURCE_ADDRESS)
PIM_ENCODED_SOURCE_ADDRESS_HDR_LEN = struct.calcsize(PIM_ENCODED_SOURCE_ADDRESS_HDR % IPV4_HDR)
PIM_ENCODED_SOURCE_ADDRESS_HDR_LEN_IPV6 = struct.calcsize(PIM_ENCODED_SOURCE_ADDRESS_HDR % IPV6_HDR)
......@@ -39,7 +40,8 @@ class PacketPimEncodedSourceAddress:
def bytes(self) -> bytes:
(string_ip_hdr, hdr_addr_family, socket_family) = PacketPimEncodedSourceAddress.get_ip_info(self.source_address)
if self.mask_len is None:
mask_len = self.mask_len
if mask_len is None:
mask_len = 8 * struct.calcsize(string_ip_hdr)
ip = socket.inet_pton(socket_family, self.source_address)
......@@ -55,4 +57,24 @@ class PacketPimEncodedSourceAddress:
elif version == 6:
return (PacketPimEncodedSourceAddress.IPV6_HDR, PacketPimEncodedSourceAddress.FAMILY_IPV6, socket.AF_INET6)
else:
raise Exception
\ No newline at end of file
raise Exception
@staticmethod
def parse_bytes(data: bytes):
data_without_source_addr = data[0:PacketPimEncodedSourceAddress.PIM_ENCODED_SOURCE_ADDRESS_HDR_WITHOUT_SOURCE_ADDRESS_LEN]
(addr_family, encoding, _, mask_len) = struct.unpack(PacketPimEncodedSourceAddress.PIM_ENCODED_SOURCE_ADDRESS_HDR_WITHOUT_SOURCE_ADDRESS, data_without_source_addr)
data_source_addr = data[PacketPimEncodedSourceAddress.PIM_ENCODED_SOURCE_ADDRESS_HDR_WITHOUT_SOURCE_ADDRESS_LEN:]
ip = None
if addr_family == PacketPimEncodedSourceAddress.FAMILY_IPV4:
(ip,) = struct.unpack("! " + PacketPimEncodedSourceAddress.IPV4_HDR, data_source_addr[:4])
ip = socket.inet_ntop(socket.AF_INET, ip)
elif addr_family == PacketPimEncodedSourceAddress.FAMILY_IPV6:
(ip,) = struct.unpack("! " + PacketPimEncodedSourceAddress.IPV6_HDR, data_source_addr[:16])
ip = socket.inet_ntop(socket.AF_INET6, ip)
if encoding != 0:
print("unknown encoding")
raise Exception
return PacketPimEncodedSourceAddress(ip, mask_len)
......@@ -16,6 +16,7 @@ class PacketPimEncodedUnicastAddress:
IPV6_HDR = "16s"
# TODO ver melhor versao ip
PIM_ENCODED_UNICAST_ADDRESS_HDR_WITHOUT_UNICAST_ADDRESS_LEN = struct.calcsize(PIM_ENCODED_UNICAST_ADDRESS_HDR_WITHOUT_UNICAST_ADDRESS)
PIM_ENCODED_UNICAST_ADDRESS_HDR_LEN = struct.calcsize(PIM_ENCODED_UNICAST_ADDRESS_HDR % IPV4_HDR)
PIM_ENCODED_UNICAST_ADDRESS_HDR_LEN_IPV6 = struct.calcsize(PIM_ENCODED_UNICAST_ADDRESS_HDR % IPV6_HDR)
......@@ -46,3 +47,22 @@ class PacketPimEncodedUnicastAddress:
return (PacketPimEncodedUnicastAddress.IPV6_HDR, PacketPimEncodedUnicastAddress.FAMILY_IPV6, socket.AF_INET6)
else:
raise Exception
@staticmethod
def parse_bytes(data: bytes):
data_without_unicast_addr = data[0:PacketPimEncodedUnicastAddress.PIM_ENCODED_UNICAST_ADDRESS_HDR_WITHOUT_UNICAST_ADDRESS_LEN]
(addr_family, encoding) = struct.unpack(PacketPimEncodedUnicastAddress.PIM_ENCODED_UNICAST_ADDRESS_HDR_WITHOUT_UNICAST_ADDRESS, data_without_unicast_addr)
data_unicast_addr = data[PacketPimEncodedUnicastAddress.PIM_ENCODED_UNICAST_ADDRESS_HDR_WITHOUT_UNICAST_ADDRESS_LEN:]
if addr_family == PacketPimEncodedUnicastAddress.FAMILY_IPV4:
(ip,) = struct.unpack("! " + PacketPimEncodedUnicastAddress.IPV4_HDR, data_unicast_addr[:4])
ip = socket.inet_ntop(socket.AF_INET, ip)
elif addr_family == PacketPimEncodedUnicastAddress.FAMILY_IPV6:
(ip,) = struct.unpack("! " + PacketPimEncodedUnicastAddress.IPV6_HDR, data_unicast_addr[:16])
ip = socket.inet_ntop(socket.AF_INET6, ip)
if encoding != 0:
print("unknown encoding")
raise Exception
return PacketPimEncodedUnicastAddress(ip)
import struct
from Packet.PacketPimHello import PacketPimHello
from Packet.PacketPimJoinPrune import PacketPimJoinPrune
from utils import checksum
'''
......@@ -29,3 +32,42 @@ class PacketPimHeader:
pim_checksum = checksum(msg_without_chcksum)
msg = msg_without_chcksum[0:2] + struct.pack("! H", pim_checksum) + msg_without_chcksum[4:]
return msg
@staticmethod
def parse_bytes(data: bytes):
# print("parsePimHdr: ", msg.encode("hex"))
print("parsePimHdr: ", data)
pim_hdr = data[0:PacketPimHeader.PIM_HDR_LEN]
(pim_ver_type, reserved, rcv_checksum) = struct.unpack(PacketPimHeader.PIM_HDR, pim_hdr)
print(pim_ver_type, reserved, rcv_checksum)
pim_version = (pim_ver_type & 0xF0) >> 4
pim_type = pim_ver_type & 0x0F
if pim_version != PacketPimHeader.PIM_VERSION:
print("Version of PIM packet received not known (!=2)")
raise Exception
msg_to_checksum = data[0:2] + b'\x00\x00' + data[4:]
print("checksum calculated: " + str(checksum(msg_to_checksum)))
if checksum(msg_to_checksum) != rcv_checksum:
print("wrong checksum")
raise Exception
pim_payload = data[PacketPimHeader.PIM_HDR_LEN:]
if pim_type == 0: # hello
pim_payload = PacketPimHello.parse_bytes(pim_payload)
elif pim_type == 3: # join/prune
pim_payload = PacketPimJoinPrune.parse_bytes(pim_payload)
print("hold_time = ", pim_payload.hold_time)
print("upstream_neighbor = ", pim_payload.upstream_neighbor_address)
for i in pim_payload.groups:
print(i.multicast_group)
print(i.joined_src_addresses)
print(i.pruned_src_addresses)
else:
raise Exception
return PacketPimHeader(pim_payload)
......@@ -47,3 +47,26 @@ class PacketPimHello:
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'))
return res
@staticmethod
def parse_bytes(data: bytes):
pim_payload = PacketPimHello()
while data != b'':
(option_type, option_length) = struct.unpack(PacketPimHello.PIM_HDR_OPTS,
data[:PacketPimHello.PIM_HDR_OPTS_LEN])
print(option_type, option_length)
data = data[PacketPimHello.PIM_HDR_OPTS_LEN:]
print(data)
(option_value,) = struct.unpack("! " + str(option_length) + "s", data[:option_length])
option_value_number = int.from_bytes(option_value, byteorder='big')
print("option value: ", option_value_number)
'''
options_list.append({"OPTION TYPE": option_type,
"OPTION LENGTH": option_length,
"OPTION VALUE": option_value_number
})
'''
pim_payload.add_option(option_type, option_value_number)
data = data[option_length:]
return pim_payload
......@@ -45,3 +45,22 @@ class PacketPimJoinPrune:
msg += multicast_group.bytes()
return msg
@staticmethod
def parse_bytes(data: bytes):
upstream_neighbor_addr_obj = PacketPimEncodedUnicastAddress.parse_bytes(data)
upstream_neighbor_addr_len = len(upstream_neighbor_addr_obj.bytes())
data = data[upstream_neighbor_addr_len:]
(_, num_groups, hold_time) = struct.unpack(PacketPimJoinPrune.PIM_HDR_JOIN_PRUNE_WITHOUT_ADDRESS, data[:PacketPimJoinPrune.PIM_HDR_JOIN_PRUNE_WITHOUT_ADDRESS_LEN])
data = data[PacketPimJoinPrune.PIM_HDR_JOIN_PRUNE_WITHOUT_ADDRESS_LEN:]
pim_payload = PacketPimJoinPrune(upstream_neighbor_addr_obj.unicast_address, hold_time)
for i in range(0, num_groups):
group = PacketPimJoinPruneMulticastGroup.parse_bytes(data)
group_len = len(group.bytes())
pim_payload.add_multicast_group(group)
data = data[group_len:]
return pim_payload
......@@ -71,3 +71,29 @@ class PacketPimJoinPruneMulticastGroup:
pruned_src_address_bytes = PacketPimEncodedSourceAddress(pruned_src_address).bytes()
msg += pruned_src_address_bytes
return msg
@staticmethod
def parse_bytes(data: bytes):
multicast_group_addr_obj = PacketPimEncodedGroupAddress.parse_bytes(data)
multicast_group_addr_len = len(multicast_group_addr_obj.bytes())
data = data[multicast_group_addr_len:]
number_join_prune_data = data[:PacketPimJoinPruneMulticastGroup.PIM_HDR_JOIN_PRUNE_MULTICAST_GROUP_WITHOUT_GROUP_ADDRESS_LEN]
(number_joined_sources, number_pruned_sources) = struct.unpack(PacketPimJoinPruneMulticastGroup.PIM_HDR_JOIN_PRUNE_MULTICAST_GROUP_WITHOUT_GROUP_ADDRESS, number_join_prune_data)
joined = []
pruned = []
data = data[PacketPimJoinPruneMulticastGroup.PIM_HDR_JOIN_PRUNE_MULTICAST_GROUP_WITHOUT_GROUP_ADDRESS_LEN:]
for i in range(0, number_joined_sources):
joined_obj = PacketPimEncodedSourceAddress.parse_bytes(data)
joined_obj_len = len(joined_obj.bytes())
data = data[joined_obj_len:]
joined.append(joined_obj.source_address)
for i in range(0, number_pruned_sources):
pruned_obj = PacketPimEncodedSourceAddress.parse_bytes(data)
pruned_obj_len = len(pruned_obj.bytes())
data = data[pruned_obj_len:]
pruned.append(pruned_obj.source_address)
return PacketPimJoinPruneMulticastGroup(multicast_group_addr_obj.group_address, joined, pruned)
......@@ -14,111 +14,8 @@ class ReceivedPacket(Packet):
self.interface = interface
# Parse ao packet e preencher objeto Packet
x = ReceivedPacket.parseIpHdr(raw_packet[:PacketIpHeader.IP_HDR_LEN])
print(x["HLEN"])
msg_without_ip_hdr = raw_packet[x["HLEN"]:]
self.ip_header = PacketIpHeader(x["SRC"])
# print(msg_without_ip_hdr)
packet_ip_hdr = raw_packet[:PacketIpHeader.IP_HDR_LEN]
self.ip_header = PacketIpHeader.parse_bytes(packet_ip_hdr)
pim_hdr = ReceivedPacket.parsePimHdr(msg_without_ip_hdr[0:PacketPimHeader.PIM_HDR_LEN])
msg_to_checksum = msg_without_ip_hdr[0:2] + b'\x00\x00' + msg_without_ip_hdr[4:]
print("checksum calculated: " + str(checksum(msg_to_checksum)))
if checksum(msg_to_checksum) != pim_hdr["CHECKSUM"]:
print("wrong checksum")
return # TODO: maybe excepcao
print(pim_hdr)
pim_payload = None
if pim_hdr["TYPE"] == 0: # hello
pim_payload = PacketPimHello()
pim_options = ReceivedPacket.parsePimHelloOpts(msg_without_ip_hdr[PacketPimHeader.PIM_HDR_LEN:])
print(pim_options)
for option in pim_options:
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())
def parseIpHdr(msg):
(verhlen, tos, iplen, ipid, frag, ttl, proto, cksum, src, dst) = \
struct.unpack(PacketIpHeader.IP_HDR, msg)
ver = (verhlen & 0xf0) >> 4
hlen = (verhlen & 0x0f) * 4
return {"VER": ver,
"HLEN": hlen,
"TOS": tos,
"IPLEN": iplen,
"IPID": ipid,
"FRAG": frag,
"TTL": ttl,
"PROTO": proto,
"CKSUM": cksum,
"SRC": socket.inet_ntoa(src),
"DST": socket.inet_ntoa(dst)
}
def parsePimHdr(msg):
# print("parsePimHdr: ", msg.encode("hex"))
print("parsePimHdr: ", msg)
(pim_ver_type, reserved, checksum) = struct.unpack(PacketPimHeader.PIM_HDR, msg)
print(pim_ver_type, reserved, checksum)
return {"PIM VERSION": (pim_ver_type & 0xF0) >> 4,
"TYPE": pim_ver_type & 0x0F,
"RESERVED": reserved,
"CHECKSUM": checksum
}
def parsePimHelloOpts(msg):
options_list = []
# print(msg)
while msg != b'':
(option_type, option_length) = struct.unpack(PacketPimHello.PIM_HDR_OPTS,
msg[:PacketPimHello.PIM_HDR_OPTS_LEN])
print(option_type, option_length)
msg = msg[PacketPimHello.PIM_HDR_OPTS_LEN:]
print(msg)
(option_value,) = struct.unpack("! " + str(option_length) + "s", msg[:option_length])
option_value_number = int.from_bytes(option_value, byteorder='big')
print("option value: ", option_value_number)
options_list.append({"OPTION TYPE": option_type,
"OPTION LENGTH": option_length,
"OPTION VALUE": option_value_number
})
msg = msg[option_length:]
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
packet_without_ip_hdr = raw_packet[self.ip_header.hdr_length:]
self.pim_header = PacketPimHeader.parse_bytes(packet_without_ip_hdr)
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