0
votes

The "frame check sequence" is a 32-bit CRC "checksum" over the entire Ethernet frame, starting with the DMAC and covering the SMAC, type, and payload. It's transmitted as the last four bytes of an Ethernet frame, just before the interpacket gap.

I expect Scapy's Ether() method to have an argument for a packet attribute for this field. It does not.

Note that Scapy methods like IP() and TCP()/UDP() contain a checksum argument ("chksum") for the additional checksums defined for those protocols.

For example...

> IP( raw(UDP(chksum=0) / IP(version=4, chksum(0)) )
<IP  version=0 ihl=0 tos=0x35 len=53 id=28 flags= frag=0 ttl=69 proto=hopopt chksum=0x14 src=0.1.0.0 dst=64.0.0.0 |<Raw load='\x7f\x00\x00\x01\x7f\x00\x00\x01' |>>
> ls(Ether)
dst    : DestMACfield    = (None)
src    : SourceMACfield  = (None)
type   : XShortEnumField = (36864)
> Ether( raw(Ether()) )
<Ether dst=ff:ff:ff:ff:ff:ff src=12:34:56:78:9a:bc type=LOOP |>
> Ether.chksum()
AttributeError: chksum
1

1 Answers

1
votes

The FCS isn't implemented on Ethernet frames in Scapy for two reasons.

  • First, historically, Scapy had trouble to get a FCS if it was at the end of a packet (but that's no longer the case, as FCSField is a thing now).
  • Secondly, most OSes don't supply it by default and when they do, there's no way of knowing that there actually is a FCS other than assuming that the padding at the end of the packet is the FCS. If you feel that it should be added, you should probably open an issue on their tracker.

Original answer:

Scapy builds the chksum arguments automatically when you build a packet. Building a packet means converting it to bytes: using bytes(pkt) or raw(pkt) (or pkt.build())

For instance, show2() shows what the packet looks like when built:

>>> pkt = IP()/UDP()/ICMP()
>>> pkt.show2()
 ###[ IP ]### 
  version= 4
  ihl= 5
  tos= 0x0
  len= 36
  id= 1
  flags= 
  frag= 0
  ttl= 64
  proto= udp
  chksum= 0x7cc6   <-------
  src= 127.0.0.1
  dst= 127.0.0.1
[...]

The checksum is only calculated when it's None, so that it allows you to set a custom (incorrect) one when you need it. If you want to check what it contains, you can build the packet manually:

>>> pkt = IP(raw(pkt))
>>> pkt[IP].chksum
31942