feat: add EtherType and IP Protocol enums for enhanced packet parsing and logging
All checks were successful
Build and Deploy MITM Webserver / build (push) Successful in 9s

This commit is contained in:
2025-12-01 21:04:37 +01:00
parent 0dbade8f91
commit 6e720859ff
3 changed files with 583 additions and 41 deletions

View File

@@ -0,0 +1,139 @@
from enum import Enum
from typing import Dict
"""
This module defines an enumeration for Ethernet frame types (EtherTypes) and provides a mapping
from numeric EtherType values to their corresponding enum representation.
Source: https://en.wikipedia.org/wiki/EtherType (01/12/2025)
"""
class EtherTypeEnum(str, Enum):
IPv4 = "Internet Protocol version 4"
CHAOSNET = "Chaosnet"
ARP = "Address Resolution Protocol"
WAKE_ON_LAN = "Wake-on-LAN"
SRP = "Stream Reservation Protocol"
AVTP = "Audio Video Transport Protocol"
TRILL = "IETF TRILL Protocol"
DEC_MOP_RC = "DEC MOP RC"
DECNET_PHASE_IV = "DECnet Phase IV / DNA Routing"
DEC_LAT = "DEC Local Area Transport"
RARP = "Reverse Address Resolution Protocol"
APPLETALK = "AppleTalk (EtherTalk)"
IBM_SNA = "IBM SNA / LLC PDU"
AARP = "AppleTalk Address Resolution Protocol"
VLAN_8021Q = "VLAN-tagged (802.1Q)"
SLPP = "Simple Loop Prevention Protocol"
VLACP = "Virtual Link Aggregation Control Protocol"
IPX = "IPX"
QNX_QNET = "QNX Qnet"
IPv6 = "Internet Protocol version 6"
FLOW_CONTROL = "Ethernet Flow Control"
SLOW_PROTOCOLS = "Ethernet Slow Protocols (LACP)"
COBRANET = "CobraNet"
MPLS_UNICAST = "MPLS Unicast"
MPLS_MULTICAST = "MPLS Multicast"
PPPoE_DISCOVERY = "PPPoE Discovery Stage"
PPPoE_SESSION = "PPPoE Session Stage"
HOMEPLUG = "HomePlug 1.0 MME"
EAPOL = "EAP over LAN (802.1X)"
PROFINET = "PROFINET Protocol"
HYPERSCSI = "HyperSCSI"
ATA_OVER_ETHERNET = "ATA over Ethernet"
ETHERCAT = "EtherCAT Protocol"
Q_IN_Q = "Service VLAN (Q-in-Q S-Tag)"
ETH_POWERLINK = "Ethernet Powerlink"
GOOSE = "Generic Substation Events (GOOSE)"
GSE = "GSE Management Services"
SV = "Sampled Value Transmission"
MIKROTIK_ROMON = "MikroTik RoMON"
LLDP = "Link Layer Discovery Protocol"
SERCOS_III = "SERCOS III"
HOMEPLUG_GREENPHY = "HomePlug Green PHY"
MRP = "Media Redundancy Protocol"
MACSEC = "MAC Security (MACsec)"
PBB = "Provider Backbone Bridges (PBB)"
PTP = "Precision Time Protocol over Ethernet"
NC_SI = "NC-SI"
PRP = "Parallel Redundancy Protocol"
CFM = "Connectivity Fault Management (802.1ag / Y.1731)"
FCoE = "Fibre Channel over Ethernet"
FCoE_INIT = "FCoE Initialization Protocol"
ROCE = "RDMA over Converged Ethernet (RoCE)"
TTE = "TTEthernet Protocol Control Frame"
IEEE_1905_1 = "1905.1 IEEE Protocol"
HSR = "High-availability Seamless Redundancy"
ETH_CONFIG_TEST = "Ethernet Configuration Testing Protocol"
REDUNDANCY_TAG = "Redundancy Tag (802.1CB)"
UNKNOWN = "Unknown EtherType"
# Mapping from integer EtherType → enum
ETHERTYPE_MAP: Dict[int, EtherTypeEnum] = {
0x0800: EtherTypeEnum.IPv4,
0x0804: EtherTypeEnum.CHAOSNET,
0x0806: EtherTypeEnum.ARP,
0x0842: EtherTypeEnum.WAKE_ON_LAN,
0x22EA: EtherTypeEnum.SRP,
0x22F0: EtherTypeEnum.AVTP,
0x22F3: EtherTypeEnum.TRILL,
0x6002: EtherTypeEnum.DEC_MOP_RC,
0x6003: EtherTypeEnum.DECNET_PHASE_IV,
0x6004: EtherTypeEnum.DEC_LAT,
0x8035: EtherTypeEnum.RARP,
0x809B: EtherTypeEnum.APPLETALK,
0x80D5: EtherTypeEnum.IBM_SNA,
0x80F3: EtherTypeEnum.AARP,
0x8100: EtherTypeEnum.VLAN_8021Q,
0x8102: EtherTypeEnum.SLPP,
0x8103: EtherTypeEnum.VLACP,
0x8137: EtherTypeEnum.IPX,
0x8204: EtherTypeEnum.QNX_QNET,
0x86DD: EtherTypeEnum.IPv6,
0x8808: EtherTypeEnum.FLOW_CONTROL,
0x8809: EtherTypeEnum.SLOW_PROTOCOLS,
0x8819: EtherTypeEnum.COBRANET,
0x8847: EtherTypeEnum.MPLS_UNICAST,
0x8848: EtherTypeEnum.MPLS_MULTICAST,
0x8863: EtherTypeEnum.PPPoE_DISCOVERY,
0x8864: EtherTypeEnum.PPPoE_SESSION,
0x887B: EtherTypeEnum.HOMEPLUG,
0x888E: EtherTypeEnum.EAPOL,
0x8892: EtherTypeEnum.PROFINET,
0x889A: EtherTypeEnum.HYPERSCSI,
0x88A2: EtherTypeEnum.ATA_OVER_ETHERNET,
0x88A4: EtherTypeEnum.ETHERCAT,
0x88A8: EtherTypeEnum.Q_IN_Q,
0x88AB: EtherTypeEnum.ETH_POWERLINK,
0x88B8: EtherTypeEnum.GOOSE,
0x88B9: EtherTypeEnum.GSE,
0x88BA: EtherTypeEnum.SV,
0x88BF: EtherTypeEnum.MIKROTIK_ROMON,
0x88CC: EtherTypeEnum.LLDP,
0x88CD: EtherTypeEnum.SERCOS_III,
0x88E1: EtherTypeEnum.HOMEPLUG_GREENPHY,
0x88E3: EtherTypeEnum.MRP,
0x88E5: EtherTypeEnum.MACSEC,
0x88E7: EtherTypeEnum.PBB,
0x88F7: EtherTypeEnum.PTP,
0x88F8: EtherTypeEnum.NC_SI,
0x88FB: EtherTypeEnum.PRP,
0x8902: EtherTypeEnum.CFM,
0x8906: EtherTypeEnum.FCoE,
0x8914: EtherTypeEnum.FCoE_INIT,
0x8915: EtherTypeEnum.ROCE,
0x891D: EtherTypeEnum.TTE,
0x893A: EtherTypeEnum.IEEE_1905_1,
0x892F: EtherTypeEnum.HSR,
0x9000: EtherTypeEnum.ETH_CONFIG_TEST,
0xF1C1: EtherTypeEnum.REDUNDANCY_TAG,
}
def ethertype_from_int(value: int) -> EtherTypeEnum:
"""
Map a numeric EtherType value to the corresponding enum.
Returns UNKNOWN if not found.
"""
return ETHERTYPE_MAP.get(value, EtherTypeEnum.UNKNOWN)

View File

@@ -0,0 +1,315 @@
from enum import Enum
"""
This module defines an enumeration for IP protocol types and provides a mapping
from numeric IP protocol values to their corresponding enum representation.
Source: https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers (01/12/2025)
"""
class IPProtocolEnum(str, Enum):
HOPOPT = "IPv6 Hop-by-Hop Option"
ICMP = "Internet Control Message Protocol"
IGMP = "Internet Group Management Protocol"
GGP = "Gateway-to-Gateway Protocol"
IP_IN_IP = "IP in IP Encapsulation"
ST = "Internet Stream Protocol"
TCP = "Transmission Control Protocol"
CBT = "Core-based Trees"
EGP = "Exterior Gateway Protocol"
IGP = "Interior Gateway Protocol"
BBN_RCC_MON = "BBN RCC Monitoring"
NVP_II = "Network Voice Protocol"
PUP = "Xerox PUP"
ARGUS = "ARGUS"
EMCON = "EMCON"
XNET = "Cross Net Debugger"
CHAOS = "Chaos Protocol"
UDP = "User Datagram Protocol"
MUX = "Multiplexing"
DCN_MEAS = "DCN Measurement Subsystems"
HMP = "Host Monitoring Protocol"
PRM = "Packet Radio Measurement"
XNS_IDP = "XEROX NS IDP"
TRUNK_1 = "Trunk 1"
TRUNK_2 = "Trunk 2"
LEAF_1 = "Leaf 1"
LEAF_2 = "Leaf 2"
RDP = "Reliable Data Protocol"
IRTP = "Internet Reliable Transaction Protocol"
ISO_TP4 = "ISO Transport Protocol Class 4"
NETBLT = "Bulk Data Transfer Protocol"
MFE_NSP = "MFE Network Services Protocol"
MERIT_INP = "MERIT Internodal Protocol"
DCCP = "Datagram Congestion Control Protocol"
THREE_PC = "Third Party Connect Protocol"
IDPR = "Inter-Domain Policy Routing"
XTP = "Xpress Transport Protocol"
DDP = "Datagram Delivery Protocol"
IDPR_CMTP = "IDPR Control Message Transport Protocol"
TP_PP = "TP++ Transport Protocol"
IL = "IL Transport Protocol"
IPV6 = "IPv6 Encapsulation"
SDRP = "Source Demand Routing Protocol"
IPV6_ROUTE = "IPv6 Routing Header"
IPV6_FRAG = "IPv6 Fragment Header"
IDRP = "Inter-Domain Routing Protocol"
RSVP = "Resource Reservation Protocol"
GRE = "Generic Routing Encapsulation"
DSR = "Dynamic Source Routing"
BNA = "Burroughs Network Architecture"
ESP = "Encapsulating Security Payload"
AH = "Authentication Header"
I_NLSP = "Integrated Net Layer Security Protocol"
SWIPE = "SwIPe"
NARP = "NBMA Address Resolution Protocol"
MOBILE = "IP Mobility"
TLSP = "Transport Layer Security Protocol"
SKIP = "Simple Key-Management for IP"
IPV6_ICMP = "ICMP for IPv6"
IPV6_NONXT = "No Next Header for IPv6"
IPV6_OPTS = "Destination Options for IPv6"
PROTO_61 = "Any host internal protocol"
CFTP = "CFTP"
PROTO_63 = "Any local network"
SAT_EXPAK = "SATNET and Backroom EXPAK"
KRYPTOLAN = "Kryptolan"
RVD = "MIT Remote Virtual Disk Protocol"
IPPC = "Internet Pluribus Packet Core"
PROTO_68 = "Any distributed file system"
SAT_MON = "SATNET Monitoring"
VISA = "VISA Protocol"
IPCU = "Internet Packet Core Utility"
CPNX = "Computer Protocol Network Executive"
CPHB = "Computer Protocol Heart Beat"
WSN = "Wang Span Network"
PVP = "Packet Video Protocol"
BR_SAT_MON = "Backroom SATNET Monitoring"
SUN_ND = "SUN ND Protocol (temporary)"
WB_MON = "Wideband Monitoring"
WB_EXPAK = "Wideband EXPAK"
ISO_IP = "International Organization for Standardization Internet Protocol"
VMTP = "Versatile Message Transaction Protocol"
SECURE_VMTP = "Secure VMTP"
VINES = "VINES"
TTP = "TTP (Transaction Transport Protocol / IPTM)"
NSFNET_IGP = "NSFNET-IGP"
DGP = "Dissimilar Gateway Protocol"
TCF = "TCF"
EIGRP = "EIGRP"
OSPF = "Open Shortest Path First"
SPRITE_RPC = "Sprite RPC Protocol"
LARP = "Locus Address Resolution Protocol"
MTP = "Multicast Transport Protocol"
AX25 = "AX.25 Packet Radio"
OS = "KA9Q NOS compatible IP over IP tunneling"
MICP = "Mobile Internetworking Control Protocol"
SCC_SP = "Semaphore Communications Security Protocol"
ETHERIP = "Ethernet-within-IP Encapsulation"
ENCAP = "Encapsulation Header"
PROTO_99 = "Any private encryption scheme"
GMTP = "GMTP"
IFMP = "Ipsilon Flow Management Protocol"
PNNI = "PNNI over IP"
PIM = "Protocol Independent Multicast"
ARIS = "IBM ARIS"
SCPS = "Space Communications Protocol Standards"
QNX = "QNX"
AN = "Active Networks"
IPCOMP = "IP Payload Compression Protocol"
SNP = "Sitara Networks Protocol"
COMPAQ_PEER = "Compaq Peer Protocol"
IPX_IN_IP = "IPX in IP"
VRRP = "Virtual Router Redundancy Protocol"
PGM = "PGM Reliable Transport Protocol"
PROTO_114 = "Any 0-hop protocol"
L2TP = "Layer Two Tunneling Protocol Version 3"
DDX = "D-II Data Exchange"
IATP = "Interactive Agent Transfer Protocol"
STP = "Schedule Transfer Protocol"
SRP = "SpectraLink Radio Protocol"
UTI = "Universal Transport Interface Protocol"
SMP = "Simple Message Protocol"
SM = "Simple Multicast Protocol"
PTP = "Performance Transparency Protocol"
ISIS = "IS-IS over IPv4"
FIRE = "Flexible Intra-AS Routing Environment"
CRTP = "Combat Radio Transport Protocol"
CRUDP = "Combat Radio User Datagram"
SSCOPMCE = "Service-Specific Connection-Oriented Protocol"
IPLT = "IPLT"
SPS = "Secure Packet Shield"
PIPE = "Private IP Encapsulation within IP"
SCTP = "Stream Control Transmission Protocol"
FC = "Fibre Channel"
RSVP_E2E_IGNORE = "RSVP End-to-End Ignore"
MOBILITY_HEADER = "Mobility Extension Header for IPv6"
UDPLITE = "UDPLite"
MPLS_IN_IP = "MPLS-in-IP"
MANET = "MANET Protocols"
HIP = "Host Identity Protocol"
SHIM6 = "Shim6"
WESP = "Wrapped Encapsulating Security Payload"
ROHC = "Robust Header Compression"
SRV6 = "Segment Routing over IPv6"
AGGFRAG = "AGGFRAG Encapsulation Payload for ESP"
NSH = "Network Service Header"
HOMA = "Homa transport protocol"
BIT_EMU = "Bit-stream Emulation"
EXPERIMENTAL_253 = "Use for experimentation (RFC 3692)"
EXPERIMENTAL_254 = "Use for experimentation (RFC 3692)"
RESERVED = "Reserved"
UNKNOWN = "Unknown"
IP_PROTOCOL_MAP = {
0: IPProtocolEnum.HOPOPT,
1: IPProtocolEnum.ICMP,
2: IPProtocolEnum.IGMP,
3: IPProtocolEnum.GGP,
4: IPProtocolEnum.IP_IN_IP,
5: IPProtocolEnum.ST,
6: IPProtocolEnum.TCP,
7: IPProtocolEnum.CBT,
8: IPProtocolEnum.EGP,
9: IPProtocolEnum.IGP,
10: IPProtocolEnum.BBN_RCC_MON,
11: IPProtocolEnum.NVP_II,
12: IPProtocolEnum.PUP,
13: IPProtocolEnum.ARGUS,
14: IPProtocolEnum.EMCON,
15: IPProtocolEnum.XNET,
16: IPProtocolEnum.CHAOS,
17: IPProtocolEnum.UDP,
18: IPProtocolEnum.MUX,
19: IPProtocolEnum.DCN_MEAS,
20: IPProtocolEnum.HMP,
21: IPProtocolEnum.PRM,
22: IPProtocolEnum.XNS_IDP,
23: IPProtocolEnum.TRUNK_1,
24: IPProtocolEnum.TRUNK_2,
25: IPProtocolEnum.LEAF_1,
26: IPProtocolEnum.LEAF_2,
27: IPProtocolEnum.RDP,
28: IPProtocolEnum.IRTP,
29: IPProtocolEnum.ISO_TP4,
30: IPProtocolEnum.NETBLT,
31: IPProtocolEnum.MFE_NSP,
32: IPProtocolEnum.MERIT_INP,
33: IPProtocolEnum.DCCP,
34: IPProtocolEnum.THREE_PC,
35: IPProtocolEnum.IDPR,
36: IPProtocolEnum.XTP,
37: IPProtocolEnum.DDP,
38: IPProtocolEnum.IDPR_CMTP,
39: IPProtocolEnum.TP_PP,
40: IPProtocolEnum.IL,
41: IPProtocolEnum.IPV6,
42: IPProtocolEnum.SDRP,
43: IPProtocolEnum.IPV6_ROUTE,
44: IPProtocolEnum.IPV6_FRAG,
45: IPProtocolEnum.IDRP,
46: IPProtocolEnum.RSVP,
47: IPProtocolEnum.GRE,
48: IPProtocolEnum.DSR,
49: IPProtocolEnum.BNA,
50: IPProtocolEnum.ESP,
51: IPProtocolEnum.AH,
52: IPProtocolEnum.I_NLSP,
53: IPProtocolEnum.SWIPE,
54: IPProtocolEnum.NARP,
55: IPProtocolEnum.MOBILE,
56: IPProtocolEnum.TLSP,
57: IPProtocolEnum.SKIP,
58: IPProtocolEnum.IPV6_ICMP,
59: IPProtocolEnum.IPV6_NONXT,
60: IPProtocolEnum.IPV6_OPTS,
62: IPProtocolEnum.CFTP,
64: IPProtocolEnum.SAT_EXPAK,
65: IPProtocolEnum.KRYPTOLAN,
66: IPProtocolEnum.RVD,
67: IPProtocolEnum.IPPC,
69: IPProtocolEnum.SAT_MON,
70: IPProtocolEnum.VISA,
71: IPProtocolEnum.IPCU,
72: IPProtocolEnum.CPNX,
73: IPProtocolEnum.CPHB,
74: IPProtocolEnum.WSN,
75: IPProtocolEnum.PVP,
76: IPProtocolEnum.BR_SAT_MON,
77: IPProtocolEnum.SUN_ND,
78: IPProtocolEnum.WB_MON,
79: IPProtocolEnum.WB_EXPAK,
80: IPProtocolEnum.ISO_IP,
81: IPProtocolEnum.VMTP,
82: IPProtocolEnum.SECURE_VMTP,
83: IPProtocolEnum.VINES,
84: IPProtocolEnum.TTP,
85: IPProtocolEnum.NSFNET_IGP,
86: IPProtocolEnum.DGP,
87: IPProtocolEnum.TCF,
88: IPProtocolEnum.EIGRP,
89: IPProtocolEnum.OSPF,
90: IPProtocolEnum.SPRITE_RPC,
91: IPProtocolEnum.LARP,
92: IPProtocolEnum.MTP,
93: IPProtocolEnum.AX25,
94: IPProtocolEnum.OS,
95: IPProtocolEnum.MICP,
96: IPProtocolEnum.SCC_SP,
97: IPProtocolEnum.ETHERIP,
98: IPProtocolEnum.ENCAP,
100: IPProtocolEnum.GMTP,
101: IPProtocolEnum.IFMP,
102: IPProtocolEnum.PNNI,
103: IPProtocolEnum.PIM,
104: IPProtocolEnum.ARIS,
105: IPProtocolEnum.SCPS,
106: IPProtocolEnum.QNX,
107: IPProtocolEnum.AN,
108: IPProtocolEnum.IPCOMP,
109: IPProtocolEnum.SNP,
110: IPProtocolEnum.COMPAQ_PEER,
111: IPProtocolEnum.IPX_IN_IP,
112: IPProtocolEnum.VRRP,
113: IPProtocolEnum.PGM,
115: IPProtocolEnum.L2TP,
116: IPProtocolEnum.DDX,
117: IPProtocolEnum.IATP,
118: IPProtocolEnum.STP,
119: IPProtocolEnum.SRP,
120: IPProtocolEnum.UTI,
121: IPProtocolEnum.SMP,
122: IPProtocolEnum.SM,
123: IPProtocolEnum.PTP,
124: IPProtocolEnum.ISIS,
125: IPProtocolEnum.FIRE,
126: IPProtocolEnum.CRTP,
127: IPProtocolEnum.CRUDP,
128: IPProtocolEnum.SSCOPMCE,
129: IPProtocolEnum.IPLT,
130: IPProtocolEnum.SPS,
131: IPProtocolEnum.PIPE,
132: IPProtocolEnum.SCTP,
133: IPProtocolEnum.FC,
134: IPProtocolEnum.RSVP_E2E_IGNORE,
135: IPProtocolEnum.MOBILITY_HEADER,
136: IPProtocolEnum.UDPLITE,
137: IPProtocolEnum.MPLS_IN_IP,
138: IPProtocolEnum.MANET,
139: IPProtocolEnum.HIP,
140: IPProtocolEnum.SHIM6,
141: IPProtocolEnum.WESP,
142: IPProtocolEnum.ROHC,
143: IPProtocolEnum.SRV6,
144: IPProtocolEnum.AGGFRAG,
145: IPProtocolEnum.NSH,
146: IPProtocolEnum.HOMA,
147: IPProtocolEnum.BIT_EMU,
253: IPProtocolEnum.EXPERIMENTAL_253,
254: IPProtocolEnum.EXPERIMENTAL_254,
255: IPProtocolEnum.RESERVED,
}
def protocol_from_number(n: int) -> IPProtocolEnum:
return IP_PROTOCOL_MAP.get(n, IPProtocolEnum.UNKNOWN)

View File

@@ -4,7 +4,6 @@ import threading
import os
import time
from typing import List, Dict, Optional
import asyncpg
from scapy.all import (
Ether,
@@ -18,13 +17,15 @@ from scapy.all import (
Dot1Q,
Raw,
)
# ---- New imports for AF_PACKET optimized reader ----------------------
import socket
import selectors
import errno
import struct
from src.Models.etherType import EtherTypeEnum, ethertype_from_int
from src.Models.ip_protocol import IPProtocolEnum, protocol_from_number
# ---- Logging ----------------------------------------------------------
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("af_packet_sniffer")
@@ -170,7 +171,7 @@ async def db_insert_packet(pkt_info: dict, bridge: str) -> None:
pkt_info.get("vlan_id"),
pkt_info.get("src_ip"),
pkt_info.get("dst_ip"),
pkt_info.get("protocol_name"),
pkt_info.get("protocol"),
pkt_info.get("src_port"),
pkt_info.get("dst_port"),
pkt_info["length"],
@@ -192,13 +193,15 @@ def parse_packet(pkt, bridge: str) -> None:
Parse a scapy packet object and collect a normalized dict of metadata
which is then scheduled to be written to the database asynchronously.
The function expects that 'pkt' is a Scapy Packet and that we set
'pkt.sniffed_on' before calling this function.
Enhancements:
- Uses EtherType and IP Protocol enums (human-readable) for API documentation.
- Records both raw numeric values and enum descriptions.
- Proper VLAN handling (Dot1Q inner ethertype).
- Keeps `protocol_name` (string) for backward compatibility.
"""
pkt_iface = getattr(pkt, "sniffed_on", None)
if not pkt_iface:
# If sniffed_on is missing we cannot determine the interface context;
# skip this packet.
# If sniffed_on is missing we cannot determine the interface context; skip this packet.
return
logger.debug("Packet captured on %s, bridge %s", pkt_iface, bridge)
@@ -210,78 +213,163 @@ def parse_packet(pkt, bridge: str) -> None:
"raw": bytes(pkt),
"src_mac": None,
"dst_mac": None,
"eth_type": None,
# eth types: both raw numeric and enum/description
"eth_type_raw": None,
"eth_type": EtherTypeEnum.UNKNOWN, # enum / human description
"vlan_id": None,
# IP protocol: raw numeric and enum/description
"protocol_raw": None,
"protocol": IPProtocolEnum.UNKNOWN,
# backward-compatible string label (older code)
"protocol_name": None,
# L3/L4 fields
"src_ip": None,
"dst_ip": None,
"protocol_name": None,
"src_port": None,
"dst_port": None,
}
# --- Layer extraction ---
# Ethernet layer
# Ethernet layer + EtherType
if Ether in pkt:
pkt_info["src_mac"] = pkt[Ether].src
pkt_info["dst_mac"] = pkt[Ether].dst
pkt_info["eth_type"] = hex(pkt[Ether].type)
try:
pkt_info["src_mac"] = pkt[Ether].src
except Exception:
pkt_info["src_mac"] = None
try:
pkt_info["dst_mac"] = pkt[Ether].dst
except Exception:
pkt_info["dst_mac"] = None
# VLAN (802.1Q)
if Dot1Q in pkt:
pkt_info["vlan_id"] = pkt[Dot1Q].vlan
# Base ethertype (may be 0x8100 for VLAN)
eth_type_raw: Optional[int] = None
try:
eth_type_raw = int(pkt[Ether].type)
except Exception:
eth_type_raw = None
# ARP
# VLAN (Dot1Q) may contain the inner ethertype
if Dot1Q in pkt:
try:
# Dot1Q.type is the encapsulated ethertype
inner = int(pkt[Dot1Q].type)
if inner:
eth_type_raw = inner
except Exception:
# ignore and keep whatever eth_type_raw was
pass
# capture vlan id if present
try:
pkt_info["vlan_id"] = int(pkt[Dot1Q].vlan)
except Exception:
pkt_info["vlan_id"] = None
# Fill eth_type fields (raw + enum)
if eth_type_raw is not None:
pkt_info["eth_type_raw"] = eth_type_raw
try:
pkt_info["eth_type"] = ethertype_from_int(eth_type_raw)
except Exception:
pkt_info["eth_type"] = EtherTypeEnum.UNKNOWN
else:
# Unknown / missing ethertype
pkt_info["eth_type_raw"] = None
pkt_info["eth_type"] = EtherTypeEnum.UNKNOWN
# ARP (layer 2/3)
if ARP in pkt:
pkt_info["protocol_name"] = "ARP"
pkt_info["src_ip"] = pkt[ARP].psrc
pkt_info["dst_ip"] = pkt[ARP].pdst
pkt_info["src_ip"] = getattr(pkt[ARP], "psrc", None)
pkt_info["dst_ip"] = getattr(pkt[ARP], "pdst", None)
pkt_info["src_port"] = None
pkt_info["dst_port"] = None
# ARP is a L2 protocol — leave protocol_raw/protocol as UNKNOWN (or set to a sentinel if desired)
# IPv4
if IP in pkt:
pkt_info["src_ip"] = pkt[IP].src
pkt_info["dst_ip"] = pkt[IP].dst
proto = pkt[IP].proto
if proto == 6 and TCP in pkt:
try:
pkt_info["src_ip"] = pkt[IP].src
except Exception:
pkt_info["src_ip"] = None
try:
pkt_info["dst_ip"] = pkt[IP].dst
except Exception:
pkt_info["dst_ip"] = None
# protocol number (IPv4 'protocol' field)
try:
proto_num = int(pkt[IP].proto)
except Exception:
proto_num = None
if proto_num is not None:
pkt_info["protocol_raw"] = proto_num
try:
pkt_info["protocol"] = protocol_from_number(proto_num)
except Exception:
pkt_info["protocol"] = IPProtocolEnum.UNKNOWN
# Common transports
if proto_num == 6 and TCP in pkt:
pkt_info["protocol_name"] = "TCP"
pkt_info["src_port"] = pkt[TCP].sport
pkt_info["dst_port"] = pkt[TCP].dport
elif proto == 17 and UDP in pkt:
pkt_info["src_port"] = getattr(pkt[TCP], "sport", None)
pkt_info["dst_port"] = getattr(pkt[TCP], "dport", None)
elif proto_num == 17 and UDP in pkt:
pkt_info["protocol_name"] = "UDP"
pkt_info["src_port"] = pkt[UDP].sport
pkt_info["dst_port"] = pkt[UDP].dport
elif proto == 1 and ICMP in pkt:
pkt_info["src_port"] = getattr(pkt[UDP], "sport", None)
pkt_info["dst_port"] = getattr(pkt[UDP], "dport", None)
elif proto_num == 1 and ICMP in pkt:
pkt_info["protocol_name"] = "ICMP"
else:
pkt_info["protocol_name"] = f"IP_PROTO_{proto}"
# leave protocol_name as numeric fallback if not matched
if pkt_info["protocol_name"] is None:
pkt_info["protocol_name"] = f"IP_PROTO_{proto_num}" if proto_num is not None else None
# IPv6
if IPv6 in pkt:
pkt_info["src_ip"] = pkt[IPv6].src
pkt_info["dst_ip"] = pkt[IPv6].dst
nh = pkt[IPv6].nh
try:
pkt_info["src_ip"] = pkt[IPv6].src
except Exception:
pkt_info["src_ip"] = None
try:
pkt_info["dst_ip"] = pkt[IPv6].dst
except Exception:
pkt_info["dst_ip"] = None
# next header / nh value
try:
nh = int(pkt[IPv6].nh)
except Exception:
nh = None
if nh is not None:
pkt_info["protocol_raw"] = nh
try:
pkt_info["protocol"] = protocol_from_number(nh)
except Exception:
pkt_info["protocol"] = IPProtocolEnum.UNKNOWN
if nh == 6 and TCP in pkt:
pkt_info["protocol_name"] = "TCP"
pkt_info["src_port"] = pkt[TCP].sport
pkt_info["dst_port"] = pkt[TCP].dport
pkt_info["src_port"] = getattr(pkt[TCP], "sport", None)
pkt_info["dst_port"] = getattr(pkt[TCP], "dport", None)
elif nh == 17 and UDP in pkt:
pkt_info["protocol_name"] = "UDP"
pkt_info["src_port"] = pkt[UDP].sport
pkt_info["dst_port"] = pkt[UDP].dport
pkt_info["src_port"] = getattr(pkt[UDP], "sport", None)
pkt_info["dst_port"] = getattr(pkt[UDP], "dport", None)
elif ICMPv6Unknown in pkt:
pkt_info["protocol_name"] = "ICMPv6"
else:
pkt_info["protocol_name"] = f"IPV6_PROTO_{nh}"
if pkt_info["protocol_name"] is None:
pkt_info["protocol_name"] = f"IPV6_PROTO_{nh}" if nh is not None else None
# Raw payload / fallback protocol label
if Raw in pkt and not pkt_info["protocol_name"]:
pkt_info["protocol_name"] = "RAW"
# Submit DB insert to background asyncio loop from this thread.
# Submit DB insert to background asyncio loop from this thread
asyncio.run_coroutine_threadsafe(db_insert_packet(pkt_info, bridge), async_loop)
# -------------------------
# AF_PACKET optimized reader
# -------------------------