original_docstring: Analyze an Ethernet packet or a Cooked Linux one
docstring: Analyze an Ethernet packet or a Cooked Linux one
docstring_tokens: Analyze an Ethernet packet or a Cooked Linux one
code: def analyze_ether_packet(self, ethpkt, is_cookedlinux=False):
          """Analyze an Ethernet packet or a Cooked Linux one"""
          base_pkt = ethpkt
          if is_cookedlinux:
              pkt_type = base_pkt.proto
              hex_hw_src = binascii.hexlify(base_pkt.src).decode('ascii')
              hw_src = ':'.join(hex_hw_src[i:i + 2] for i in range(0, 12, 2))
              hw_dst = None
              if base_pkt.pkttype == 1:  # Broadcast
                  hw_dst = 'ff:ff:ff:ff:ff:ff'
          else:
              pkt_type = base_pkt.type
              hw_src = ethpkt.src
              hw_dst = ethpkt.dst
  
          while pkt_type == 0x8100:  # IEEE 802.1Q VLAN (Virtual Local Area Network)
              base_pkt = base_pkt[1]
              assert isinstance(base_pkt, Dot1Q)
              pkt_type = base_pkt.type
  
          if pkt_type == 4:  # 802.2 LLC (Logical Link Control)
              # This packet may contain an STP payload which indicates a bridge,
              # but it is not parsed well by scapy.
              # In order to get it: configure a bridge on a Linux machine and
              # capture traffic on interface "any".
              return
          if pkt_type == 8:  # LLC (Logical Link Control)
              return
          if pkt_type == 0x800:  # IPv4
              ippkt = base_pkt[1]
              assert isinstance(ippkt, IP)
              self.hwaddrdb.add_ipv4(ippkt.src, hw_src, 'IPv4 packet source')
              if hw_dst is not None:
                  self.hwaddrdb.add_ipv4(ippkt.dst, hw_dst, 'IPv4 packet destination')
              self.analyze_ipv4_packet(ippkt)
              return
          if pkt_type == 0x806:  # ARP
              arppkt = base_pkt[1]
              assert isinstance(arppkt, ARP)
              if arppkt.op == 1:  # ARP who-has?
                  self.hwaddrdb.add_ipv4(arppkt.psrc, arppkt.hwsrc, 'ARP who-has? source')
              elif arppkt.op == 2:  # ARP is-at
                  self.hwaddrdb.add_ipv4(arppkt.psrc, arppkt.hwsrc, 'ARP is-at source')
                  self.hwaddrdb.add_ipv4(arppkt.pdst, arppkt.hwdst, 'ARP is-at destination')
              else:
                  logger.warning("Unknown ARP packet %r", arppkt)
              return
          if pkt_type == 0x2600 and hw_dst == 'ff:ff:ff:ff:ff:ff' and isinstance(base_pkt[1], Raw):
              # AeroHive LLC messages (filter in Wireshark with "eth.type == 0x2600")
              aerohive_data = base_pkt[1].load
              if aerohive_data.startswith(b'\x00\x00\xaf\x81\x01\x00aerohive gratuitous arp'):
                  logger.debug("Seen AeroHive[%s] %r", hw_src, aerohive_data[15:].rstrip(b'\0'))
                  if not self.seen_eth_0x2600_aerohive:
                      logger.info(
                          "Broadcast AeroHive Gratuitous ARP found in capture. Maybe an AeroHive WiFi network (%r)",
                          ethpkt)
                      self.seen_eth_0x2600_aerohive = True
                  return
          if pkt_type == 0x6002:  # DNA_RC, for Decnet Maintenance Operation Protocol (MOP) Remote Console (RC)
              if hw_dst != 'ab:00:00:02:00:00':
                  logger.warning("Unexpected Ethernet destination for DEC MOP DNA_RC packet: %r", ethpkt)
              elif not self.seen_eth_0x6002_dec_mop_dna_rc:
                  logger.info(
                      "DEC MOP DNA_RC packet found in capture. This may signal a Cisco router (%r)",
                      ethpkt)
                  self.seen_eth_0x6002_dec_mop_dna_rc = True
              return
          if pkt_type == 0x8035:  # Reverse ARP (https://tools.ietf.org/html/rfc903)
              rarppkt = base_pkt[1]
              assert isinstance(rarppkt, Raw)
              # Ignore RARP request for IPv4 address:
              # - hardware type: Ethernet (1)
              # - protocol type: IPv4 (0x0800)
              # - hardware size: 6
              # - protocol size: 4
              # - opcode: reverse request (3) or reverse response (4)
              if rarppkt.load.startswith(b'\x00\x01\x08\x00\x06\x04\x00\x03'):
                  pass
              else:
                  logger.warning("Unknown RARP packet: %r", ethpkt)
              return
          if pkt_type == 0x86dd:  # IPv6
              ippkt = base_pkt[1]
              assert isinstance(ippkt, IPv6)
              self.hwaddrdb.add_ipv6(ippkt.src, hw_src, 'IPv6 packet source')
              if hw_dst is not None:
                  self.hwaddrdb.add_ipv6(ippkt.dst, hw_dst, 'IPv6 packet destination')
              self.analyze_ipv6_packet(ippkt)
              return
          if pkt_type == 0x887b and hw_dst == 'ff:ff:ff:ff:ff:ff':
              # Homeplug, broadcasted protocol, eventually in a VLAN 101 in a home network
              if not self.seen_eth_0x887b_homeplug:
                  logger.info(
                      "Homeplug heartbit found in capture: %r",
                      ethpkt)
                  self.seen_eth_0x887b_homeplug = True
              return
          if pkt_type == 0x888e:  # EAPOL (IEEE 802.1X)
              return
          if pkt_type in (0x8890, 0x8891, 0x8893):
              # Fortinet hardware uses these special ethernet types
              # https://help.fortinet.com/fos50hlp/56/Content/FortiOS/fortigate-high-availability/HA_failoverHeartbeat.htm
              if not self.seen_eth_0x889x_fortinet:
                  logger.info(
                      "Fortinet Heartbeat found in capture. This may give useful information about the network (%r)",
                      ethpkt)
                  self.seen_eth_0x889x_fortinet = True
              return
          if pkt_type == 0x88cc:  # LLDP
              # Scapy does not understand LLDP, but Wireshark does.
              # These packets may given VLAN IDs and network names.
              if not self.seen_eth_0x88cc_lldp:
                  logger.info(
                      "LLDP found in packet capture. This may give useful information about the network (%r)",
                      ethpkt)
                  # logger.debug("Skipping LLDP packet %r", ethpkt)
                  self.seen_eth_0x88cc_lldp = True
              return
          if pkt_type == 0x88d9:  # LLTD (Link Layer Topology Discovery)
              if not self.seen_eth_0x88d9_lltd:
                  logger.info(
                      "LLTP found in packet capture. This may give useful information about the network (%r)",
                      ethpkt)
                  self.seen_eth_0x88d9_lltd = True
              return
          if pkt_type == 0x88e1 and hw_dst == 'ff:ff:ff:ff:ff:ff':
              # Homeplug AV, broadcasted protocol, eventually in a VLAN 101 in a home network
              # in Wireshark: "HomePlug AV: CM_BRG_INFO.REQ (Get Bridge Information Request)"
              if not self.seen_eth_0x88e1_homeplug_av:
                  logger.info(
                      "Homeplug AV packet found in capture: %r",
                      ethpkt)
                  self.seen_eth_0x88e1_homeplug_av = True
              return
          if pkt_type == 0x890d:  # IEEE 802.11 data encapsulation (WiFi)
              # The source MAC address is probably a WiFi access point on a wired network
              self.hwaddrdb.add_bridge(hw_src)
              if not self.seen_eth_0x890d_802_11:
                  logger.info(
                      "Encapsulated 802.11 data found, probably emitted by a WiFi access point (%r)",
                      ethpkt)
                  self.seen_eth_0x890d_802_11 = True
              return
          if pkt_type == 0x9000:  # Configuration Test Protocol (loopback), from a Cisco switch
              self.hwaddrdb.add_bridge(hw_src)
              return
  
          if pkt_type == 0x9001:  # 3Com (Formerly Bridge Communications), XNS Systems Management
              # Unknown frame, broadcasted
              if hw_dst == 'ff:ff:ff:ff:ff:ff':
                  if not self.seen_eth_0x9001:
                      logger.info(
                          "Broadcasted Ethernet 0x9001 data found, probably emitted by a switch (%r)",
                          ethpkt)
                      self.seen_eth_0x9001 = True
                  return
          logger.warning("Unknown Ethernet packet type %#x: %r", pkt_type, ethpkt)
code_tokens: def analyze_ether_packet ( self , ethpkt , is_cookedlinux = False ) : base_pkt = ethpkt if is_cookedlinux : pkt_type = base_pkt . proto hex_hw_src = binascii . hexlify ( base_pkt . src ) . decode ( 'ascii' ) hw_src = ':' . join ( hex_hw_src [ i : i + 2 ] for i in range ( 0 , 12 , 2 ) ) hw_dst = None if base_pkt . pkttype == 1 : hw_dst = 'ff:ff:ff:ff:ff:ff' else : pkt_type = base_pkt . type hw_src = ethpkt . src hw_dst = ethpkt . dst while pkt_type == 0x8100 : base_pkt = base_pkt [ 1 ] assert isinstance ( base_pkt , Dot1Q ) pkt_type = base_pkt . type if pkt_type == 4 : return if pkt_type == 8 : return if pkt_type == 0x800 : ippkt = base_pkt [ 1 ] assert isinstance ( ippkt , IP ) self . hwaddrdb . add_ipv4 ( ippkt . src , hw_src , 'IPv4 packet source' ) if hw_dst is not None : self . hwaddrdb . add_ipv4 ( ippkt . dst , hw_dst , 'IPv4 packet destination' ) self . analyze_ipv4_packet ( ippkt ) return if pkt_type == 0x806 : arppkt = base_pkt [ 1 ] assert isinstance ( arppkt , ARP ) if arppkt . op == 1 : self . hwaddrdb . add_ipv4 ( arppkt . psrc , arppkt . hwsrc , 'ARP who-has? source' ) elif arppkt . op == 2 : self . hwaddrdb . add_ipv4 ( arppkt . psrc , arppkt . hwsrc , 'ARP is-at source' ) self . hwaddrdb . add_ipv4 ( arppkt . pdst , arppkt . hwdst , 'ARP is-at destination' ) else : logger . warning ( "Unknown ARP packet %r" , arppkt ) return if pkt_type == 0x2600 and hw_dst == 'ff:ff:ff:ff:ff:ff' and isinstance ( base_pkt [ 1 ] , Raw ) : aerohive_data = base_pkt [ 1 ] . load if aerohive_data . startswith ( b'\x00\x00\xaf\x81\x01\x00aerohive gratuitous arp' ) : logger . debug ( "Seen AeroHive[%s] %r" , hw_src , aerohive_data [ 15 : ] . rstrip ( b'\0' ) ) if not self . seen_eth_0x2600_aerohive : logger . info ( "Broadcast AeroHive Gratuitous ARP found in capture. Maybe an AeroHive WiFi network (%r)" , ethpkt ) self . seen_eth_0x2600_aerohive = True return if pkt_type == 0x6002 : if hw_dst != 'ab:00:00:02:00:00' : logger . warning ( "Unexpected Ethernet destination for DEC MOP DNA_RC packet: %r" , ethpkt ) elif not self . seen_eth_0x6002_dec_mop_dna_rc : logger . info ( "DEC MOP DNA_RC packet found in capture. This may signal a Cisco router (%r)" , ethpkt ) self . seen_eth_0x6002_dec_mop_dna_rc = True return if pkt_type == 0x8035 : rarppkt = base_pkt [ 1 ] assert isinstance ( rarppkt , Raw ) if rarppkt . load . startswith ( b'\x00\x01\x08\x00\x06\x04\x00\x03' ) : pass else : logger . warning ( "Unknown RARP packet: %r" , ethpkt ) return if pkt_type == 0x86dd : ippkt = base_pkt [ 1 ] assert isinstance ( ippkt , IPv6 ) self . hwaddrdb . add_ipv6 ( ippkt . src , hw_src , 'IPv6 packet source' ) if hw_dst is not None : self . hwaddrdb . add_ipv6 ( ippkt . dst , hw_dst , 'IPv6 packet destination' ) self . analyze_ipv6_packet ( ippkt ) return if pkt_type == 0x887b and hw_dst == 'ff:ff:ff:ff:ff:ff' : if not self . seen_eth_0x887b_homeplug : logger . info ( "Homeplug heartbit found in capture: %r" , ethpkt ) self . seen_eth_0x887b_homeplug = True return if pkt_type == 0x888e : return if pkt_type in ( 0x8890 , 0x8891 , 0x8893 ) : if not self . seen_eth_0x889x_fortinet : logger . info ( "Fortinet Heartbeat found in capture. This may give useful information about the network (%r)" , ethpkt ) self . seen_eth_0x889x_fortinet = True return if pkt_type == 0x88cc : if not self . seen_eth_0x88cc_lldp : logger . info ( "LLDP found in packet capture. This may give useful information about the network (%r)" , ethpkt ) self . seen_eth_0x88cc_lldp = True return if pkt_type == 0x88d9 : if not self . seen_eth_0x88d9_lltd : logger . info ( "LLTP found in packet capture. This may give useful information about the network (%r)" , ethpkt ) self . seen_eth_0x88d9_lltd = True return if pkt_type == 0x88e1 and hw_dst == 'ff:ff:ff:ff:ff:ff' : if not self . seen_eth_0x88e1_homeplug_av : logger . info ( "Homeplug AV packet found in capture: %r" , ethpkt ) self . seen_eth_0x88e1_homeplug_av = True return if pkt_type == 0x890d : self . hwaddrdb . add_bridge ( hw_src ) if not self . seen_eth_0x890d_802_11 : logger . info ( "Encapsulated 802.11 data found, probably emitted by a WiFi access point (%r)" , ethpkt ) self . seen_eth_0x890d_802_11 = True return if pkt_type == 0x9000 : self . hwaddrdb . add_bridge ( hw_src ) return if pkt_type == 0x9001 : if hw_dst == 'ff:ff:ff:ff:ff:ff' : if not self . seen_eth_0x9001 : logger . info ( "Broadcasted Ethernet 0x9001 data found, probably emitted by a switch (%r)" , ethpkt ) self . seen_eth_0x9001 = True return logger . warning ( "Unknown Ethernet packet type %#x: %r" , pkt_type , ethpkt )
short_docstring: Analyze an Ethernet packet or a Cooked Linux one
short_docstring_tokens: Analyze an Ethernet packet or a Cooked Linux one
comment: """Analyze an Ethernet packet or a Cooked Linux one"""$SEP$# Broadcast$SEP$# IEEE 802.1Q VLAN (Virtual Local Area Network)$SEP$# 802.2 LLC (Logical Link Control)$SEP$# This packet may contain an STP payload which indicates a bridge,$SEP$# but it is not parsed well by scapy.$SEP$# In order to get it: configure a bridge on a Linux machine and$SEP$# capture traffic on interface "any".$SEP$# LLC (Logical Link Control)$SEP$# IPv4$SEP$# ARP$SEP$# ARP who-has?$SEP$# ARP is-at$SEP$# AeroHive LLC messages (filter in Wireshark with "eth.type == 0x2600")$SEP$# DNA_RC, for Decnet Maintenance Operation Protocol (MOP) Remote Console (RC)$SEP$# Reverse ARP (https://tools.ietf.org/html/rfc903)$SEP$# Ignore RARP request for IPv4 address:$SEP$# - hardware type: Ethernet (1)$SEP$# - protocol type: IPv4 (0x0800)$SEP$# - hardware size: 6$SEP$# - protocol size: 4$SEP$# - opcode: reverse request (3) or reverse response (4)$SEP$# IPv6$SEP$# Homeplug, broadcasted protocol, eventually in a VLAN 101 in a home network$SEP$# EAPOL (IEEE 802.1X)$SEP$# Fortinet hardware uses these special ethernet types$SEP$# https://help.fortinet.com/fos50hlp/56/Content/FortiOS/fortigate-high-availability/HA_failoverHeartbeat.htm$SEP$# LLDP$SEP$# Scapy does not understand LLDP, but Wireshark does.$SEP$# These packets may given VLAN IDs and network names.$SEP$# logger.debug("Skipping LLDP packet %r", ethpkt)$SEP$# LLTD (Link Layer Topology Discovery)$SEP$# Homeplug AV, broadcasted protocol, eventually in a VLAN 101 in a home network$SEP$# in Wireshark: "HomePlug AV: CM_BRG_INFO.REQ (Get Bridge Information Request)"$SEP$# IEEE 802.11 data encapsulation (WiFi)$SEP$# The source MAC address is probably a WiFi access point on a wired network$SEP$# Configuration Test Protocol (loopback), from a Cisco switch$SEP$# 3Com (Formerly Bridge Communications), XNS Systems Management$SEP$# Unknown frame, broadcasted