#import "lib/api.typ": *

// Common network protocols
#let ipv4 = bytefield(
  bitheader("bytes"),
  bits(4)[Version], bits(4)[IHL], bytes(1)[TOS], bytes(2)[Total Length],
  bytes(2)[Identification], bits(3)[Flags], bits(13)[Fragment Offset],
  bytes(1)[TTL], bytes(1)[Protocol], bytes(2)[Header Checksum],
  bytes(4)[Source Address],
  bytes(4)[Destination Address],
  bytes(3)[Options], bytes(1)[Padding]
)

#let ipv6 = bytefield(
  bitheader("bytes"),
  bits(4)[Version], bytes(1)[Traffic Class], bits(20)[Flowlabel],
  bytes(2)[Payload Length], bytes(1)[Next Header], bytes(1)[Hop Limit],
  bytes(int(128/8))[Source Address],
  bytes(int(128/8))[Destination Address],
)

#let icmp = bytefield(
  bitheader("bytes"),
  byte[Type], byte[Code], bytes(2)[Checksum],
  bytes(2)[Identifier], bytes(2)[Sequence Number],
  bits(auto)[Optional Data]
)

#let icmpv6 = bytefield(
  bitheader("bytes"),
  byte[Type], byte[Code], bytes(2)[Checksum],
  bits(auto)[Internet Header + 64 bits of Original Data Datagram]
)

#let dns = bytefield(
  bitheader("bytes"),
  bytes(2)[Identification], bytes(2)[Flags],
  bytes(2)[Number of Questions], bytes(2)[Number of answer RRs],
  bytes(2)[Number of authority RRs], bytes(2)[Number of additional RRs],
  bytes(8)[Questions],
  bytes(8)[Answers (variable number of resource records)],
  bytes(8)[Authority (variable number of resource records)],
  bytes(8)[Additional information (variable number of resource records)],
)

#let tcp = bytefield(
  bitheader("bytes"),
  bytes(2)[Source Port], bytes(2)[Destination Port],
  bytes(4)[Sequence Number],
  bytes(4)[Acknowledgment Number],
  bits(4)[Data Offset],bits(6)[Reserved], bits(6)[Flags], bytes(2)[Window],
  bytes(2)[Checksum], bytes(2)[Urgent Pointer],
  bytes(3)[Options], byte[Padding],
  bits(auto)[...DATA...]
)

#let tcp_detailed = bytefield(
  bitheader("bytes"),
  bytes(2)[Source Port], bytes(2)[ Destination Port],
  bytes(4)[Sequence Number],
  bytes(4)[Acknowledgment Number],
  bits(4)[Data Offset],bits(6)[Reserved], flag("URG"), flag("ACK"), flag("PSH"), flag("RST"), flag("SYN"), flag("FIN"), bytes(2)[Window],
  bytes(2)[Checksum], bytes(2)[Urgent Pointer],
  bytes(3)[Options], byte[Padding],
  bits(auto)[...DATA...]
)

#let udp = bytefield(
  bitheader("bytes"),
  bytes(2)[Source Port], bytes(2)[ Destination Port],
  bytes(2)[Length], bytes(2)[Checksum],
  bits(auto)[...DATA...]
)
