def __pre_parse_sanity_check(self, raw_packet, pseudo_header): """ Preliminary sanity check to be run on raw UDP packet prior to packet parsing """ if not config.pre_parse_sanity_check: return True if inet_cksum(pseudo_header + raw_packet): self.logger.critical( f"{self.tracker} - UDP sanity check fail - wrong packet checksum" ) return False if len(raw_packet) < 8: self.logger.critical( f"{self.tracker} - UDP sanity check fail - wrong packet length (I)" ) return False plen = struct.unpack("!H", raw_packet[4:6])[0] if not 8 <= plen == len(raw_packet): self.logger.critical( f"{self.tracker} - UDP sanity check fail - wrong packet length (II)" ) return False return True
def validate_cksum(self, ip_pseudo_header): """ Validate packet checksum """ # Return valid checksum if checksum is not used if not self.udp_cksum: return True return not bool(inet_cksum(ip_pseudo_header + self.raw_packet))
def __pre_parse_sanity_check(self, raw_packet): """ Preliminary sanity check to be run on raw IPv4 packet prior to packet parsing """ if not config.pre_parse_sanity_check: return True if len(raw_packet) < 20: self.logger.critical( f"{self.tracker} - IPv4 sanity check fail - wrong packet length (I)" ) return False hlen = (raw_packet[0] & 0b00001111) << 2 plen = struct.unpack("!H", raw_packet[2:4])[0] if not 20 <= hlen <= plen == len(raw_packet): self.logger.critical( f"{self.tracker} - IPv4 sanity check fail - wrong packet length (II)" ) return False # Cannot compute checksum earlier because it depends on sanity of hlen field if inet_cksum(raw_packet[:hlen]): self.logger.critical( f"{self.tracker} - IPv4 sanity check fail - wrong packet checksum" ) return False index = 20 while index < hlen: if raw_packet[index] == IP4_OPT_EOL: break if raw_packet[index] == IP4_OPT_NOP: index += 1 if index > hlen: self.logger.critical( f"{self.tracker} - IPv4 sanity check fail - wrong option length (I)" ) return False continue if index + 1 > hlen: self.logger.critical( f"{self.tracker} - IPv4 sanity check fail - wrong option length (II)" ) return False if raw_packet[index + 1] == 0: self.logger.critical( f"{self.tracker} - IPv4 sanity check fail - wrong option length (III)" ) return False index += raw_packet[index + 1] if index > hlen: self.logger.critical( f"{self.tracker} - IPv4 sanity check fail - wrong option length (IV)" ) return False return True
def __pre_parse_sanity_check(self, raw_packet, pseudo_header): """ Preliminary sanity check to be run on raw TCP packet prior to packet parsing """ if not config.pre_parse_sanity_check: return True if inet_cksum(pseudo_header + raw_packet): self.logger.critical(f"{self.tracker} - TCP sanity check fail - wrong packet checksum") return False if len(raw_packet) < 20: self.logger.critical(f"{self.tracker} - TCP sanity check fail - wrong packet length (I)") return False hlen = (raw_packet[12] & 0b11110000) >> 2 if not 20 <= hlen <= len(raw_packet): self.logger.critical(f"{self.tracker} - TCP sanity check fail - wrong packet length (II)") return False index = 20 while index < hlen: if raw_packet[index] == TCP_OPT_EOL: break if raw_packet[index] == TCP_OPT_NOP: index += 1 if index > hlen: self.logger.critical(f"{self.tracker} - TCP sanity check fail - wrong option length (I)") return False continue if index + 1 > hlen: self.logger.critical(f"{self.tracker} - TCP sanity check fail - wrong option length (II)") return False if raw_packet[index + 1] == 0: self.logger.critical(f"{self.tracker} - TCP sanity check fail - wrong option length (III)") return False index += raw_packet[index + 1] if index > hlen: self.logger.critical(f"{self.tracker} - TCP sanity check fail - wrong option length (IV)") return False return True
def __pre_parse_sanity_check(self, raw_packet): """ Preliminary sanity check to be run on raw ICMPv4 packet prior to packet parsing """ if not config.pre_parse_sanity_check: return True if inet_cksum(raw_packet): self.logger.critical( f"{self.tracker} - ICMPv4 sanity check fail - wrong packet checksum" ) return False if len(raw_packet) < 4: self.logger.critical( f"{self.tracker} - ICMPv4 sanity check fail - wrong packet length (I)" ) return False if raw_packet[0] == ICMP4_ECHOREPLY: if len(raw_packet) < 8: self.logger.critical( f"{self.tracker} - ICMPv6 sanity check fail - wrong packet length (II)" ) return False elif raw_packet[0] == ICMP4_UNREACHABLE: if len(raw_packet) < 12: self.logger.critical( f"{self.tracker} - ICMPv6 sanity check fail - wrong packet length (II)" ) return False elif raw_packet[0] == ICMP4_ECHOREQUEST: if len(raw_packet) < 8: self.logger.critical( f"{self.tracker} - ICMPv6 sanity check fail - wrong packet length (II)" ) return False return True
def handle_ip4_fragmentation(ip4_packet_rx): """ Check if packet is fragmented """ # Check if IP packet is a first fragment if ip4_packet_rx.ip4_frag_offset == 0 and ip4_packet_rx.ip4_flag_mf: ip4_fragments[ip4_packet_rx.ip4_packet_id] = {} ip4_fragments[ip4_packet_rx.ip4_packet_id][ ip4_packet_rx.ip4_frag_offset] = ip4_packet_rx.raw_data return None # Check if IP packet is one of middle fragments if ip4_packet_rx.ip4_frag_offset != 0 and ip4_packet_rx.ip4_flag_mf: # Check if packet is part of existing fagment flow if ip4_fragments.get(ip4_packet_rx.ip4_packet_id, None): ip4_fragments[ip4_packet_rx.ip4_packet_id][ ip4_packet_rx.ip4_frag_offset] = ip4_packet_rx.raw_data return None # Check if IP packet is last fragment if ip4_packet_rx.ip4_frag_offset != 0 and not ip4_packet_rx.ip4_flag_mf: # Check if packet is part of existing fagment flow if ip4_fragments.get(ip4_packet_rx.ip4_packet_id, None): ip4_fragments[ip4_packet_rx.ip4_packet_id][ ip4_packet_rx.ip4_frag_offset] = ip4_packet_rx.raw_data raw_data = b"" for offset in sorted(ip4_fragments[ip4_packet_rx.ip4_packet_id]): raw_data += ip4_fragments[ip4_packet_rx.ip4_packet_id][offset] # Craft complete IP packet based on last fragment for further processing ip4_packet_rx.ip4_flag_mf = False ip4_packet_rx.ip4_frag_offset = 0 ip4_packet_rx.ip4_plen = ip4_packet_rx.ip4_hlen + len(raw_data) ip4_packet_rx.ip4_cksum = 0 ip4_packet_rx.ip4_cksum = inet_cksum(ip4_packet_rx.raw_header) ip4_packet_rx.raw_data = raw_data return ip4_packet_rx
def get_raw_packet(self, ip_pseudo_header): """ Get packet in raw format ready to be processed by lower level protocol """ self.udp_cksum = inet_cksum(ip_pseudo_header + self.raw_packet) return self.raw_packet
def validate_cksum(self, ip_pseudo_header): """ Validate packet checksum """ return not bool(inet_cksum(ip_pseudo_header + self.raw_packet))
def validate_cksum(self): """ Validate packet checksum """ return not bool(inet_cksum(self.raw_packet))
def get_raw_packet(self): """ Get packet in raw format ready to be processed by lower level protocol """ self.icmp4_cksum = inet_cksum(self.raw_packet) return self.raw_packet
def validate_cksum(self): """ Validate packet checksum """ return not bool(inet_cksum(self.raw_header + self.raw_options))