NETProtocols
Low-level implementations of common networking protocols, in pure Python with zero dependencies.
Decode raw header bytes into typed, immutable protocol objects — or build those objects from field values and serialize them back to their exact on-wire form. Every header is a frozen dataclass whose fields mirror the wire format, so decoded traffic is introspectable, comparable, and round-trippable.
>>> from netprotocols import Ethernet
>>> eth = Ethernet.decode(frame)
>>> eth
Ethernet(dst='ff:ff:ff:ff:ff:ff', src='00:07:0d:af:f4:54', ethertype=2054)
>>> eth.ethertype_name
'ARP'
>>> eth.next_protocol()
<class 'netprotocols.layer2.arp.ARP'>
>>> bytes(eth) == frame[:eth.header_len]
True
Installation
pip install netprotocols
Requires Python 3.12+. Fully typed (py.typed, mypy strict).
Protocol coverage
| Layer | Protocol | Class | Notes |
|---|---|---|---|
| 2 | Ethernet II | Ethernet |
IEEE 802.3 |
| 2 | ARP | ARP |
RFC 826, IPv4-over-Ethernet binding |
| 3 | IPv4 | IPv4 |
RFC 791, IHL/options aware |
| 3 | IPv6 | IPv6 |
RFC 8200 |
| 3 | IPv6 Hop-by-Hop Options | IPv6HopByHopOptions |
RFC 8200 §4.3 |
| 3 | IPv6 Routing | IPv6Routing |
RFC 8200 §4.4 |
| 3 | IPv6 Fragment | IPv6Fragment |
RFC 8200 §4.5, first-fragment chaining |
| 3 | IPv6 Destination Options | IPv6DestinationOptions |
RFC 8200 §4.6 |
| 3 | ICMPv4 | ICMPv4 |
RFC 792, 8-byte header |
| 3 | ICMPv6 | ICMPv6 |
RFC 4443, 8-byte header |
| 4 | TCP | TCP |
RFC 9293, data-offset/options aware |
| 4 | UDP | UDP |
RFC 768 |
Decoding a captured frame
Each class decodes its own header from the start of a buffer and
tolerates trailing bytes, so you can walk a whole frame with two pieces
of information every header provides: header_len (how many bytes it
consumed) and next_protocol() (which class decodes what follows).
from netprotocols import Ethernet
def decode_frame(frame: bytes) -> list:
layers, cursor, protocol = [], 0, Ethernet
while protocol is not None:
header = protocol.decode(frame[cursor:])
layers.append(header)
cursor += header.header_len
protocol = header.next_protocol()
return layers # e.g. [Ethernet(...), IPv4(...), TCP(...)]
Malformed input raises exceptions rooted at a single base class:
from netprotocols import ProtocolError, TruncatedHeaderError, InvalidFieldError
try:
layers = decode_frame(frame)
except TruncatedHeaderError: # buffer shorter than the header claims
...
except InvalidFieldError: # nonsense field values (IHL < 5, bad address)
...
except ProtocolError: # catches every library error
...
Building and serializing headers
Constructors take friendly values (string MAC/IP addresses, integer
fields) and validate them; bytes() emits the exact on-wire form.
Packet concatenates a stack of layers:
from netprotocols import ARP, Ethernet, Packet, random_mac
sha = random_mac()
frame = Packet(
Ethernet(dst="ff:ff:ff:ff:ff:ff", src=sha, ethertype=0x0806),
ARP(htype=1, ptype=0x0800, hlen=6, plen=4, oper=1,
sha=sha, spa="192.168.1.96",
tha="00:00:00:00:00:00", tpa="192.168.1.254"),
)
raw = bytes(frame) # ready for a raw socket
Checksums are computed and verified on request — never silently:
compute()/verify() in netprotocols.checksum, and
Packet.with_checksums() to fill a whole stack before sending.
Display helpers
Every class exposes human-readable properties next to the raw fields:
Ethernet.ethertype_name, IPv4.protocol_name, IPv4.flags_name,
TCP.flags_str ("SYN ACK"), ARP.oper_name, ICMPv4.type_name,
and hexadecimal renderings such as checksum_hex_str. Unknown values
degrade gracefully ("0x88cc", "unknown (47)") instead of raising.
How it works
See ARCHITECTURE.md for a guided tour: how a header
byte layout maps onto a dataclass, the decode contract, the
next_protocol() chain, and a cookbook for adding a new protocol.
This library is the engine behind Packet-Sniffer, a network traffic monitor built on it.
Roadmap
- 802.1Q VLAN tags, DNS, DHCP, IGMP, GRE.
Contributing
Development uses uv: uv sync, then
uv run pytest, uv run mypy, and uv run ruff check — all three are
enforced by CI on Python 3.12–3.14. Start with
ARCHITECTURE.md.
License
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file netprotocols-1.1.0.tar.gz.
File metadata
- Download URL: netprotocols-1.1.0.tar.gz
- Upload date:
- Size: 89.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5078957c0e040304e22785746a2450143d0de2433243818efb0f707683ddfe8a
|
|
| MD5 |
edb967d3b27f9320b97b2162f922b91c
|
|
| BLAKE2b-256 |
9517e43868caed6bb29d0ba5ec601b8d167f9e93612c6fb4439395bf82a4a919
|
File details
Details for the file netprotocols-1.1.0-py3-none-any.whl.
File metadata
- Download URL: netprotocols-1.1.0-py3-none-any.whl
- Upload date:
- Size: 26.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fde3c0ca3987792f5cfb9fc08adf41b3bb98e3b0d7c2560f521fc3e0be6c37d4
|
|
| MD5 |
848e03258db6b43883d1128daca2a447
|
|
| BLAKE2b-256 |
ece21faabe3042105d1309dc8e1aa485768c35e4875a4cf5d8060da4cfadd473
|