kamene icon indicating copy to clipboard operation
kamene copied to clipboard

Big endian systems: RadioTap FlagsField incorrect

Open matt7aylor opened this issue 8 years ago • 3 comments

Hi, I'm encountering an issue processing the RadioTap headers of packets correctly on big endian systems. For example:

raw = b'\x00\x00\x1a\x00/H\x00\x00\xe1\xd3\xcb\x05\x00\x00\x00\x00@0x\x14@\x01\xac\x00\x00\x00'
r = RadioTap(raw)
r.show()

On big endian system (incorrect):

###[ RadioTap dummy ]###
  version   = 0
  pad       = 0
  len       = 26
  present   = MCS+b22+b24+b25+b26+b27+Reset
  notdecoded= b'\xe1\xd3\xcb\x05\x00\x00\x00\x00@0x\x14@\x01\xac\x00\x00\x00'

On little endian system (correct):

###[ RadioTap dummy ]###
  version   = 0
  pad       = 0
  len       = 26
  present   = TSFT+Flags+Rate+Channel+dBm_AntSignal+Antenna+RX_Flags
  tsft      = 97244129
  flags     = failed
  rate      = 48
  channel_freq= 5240
  channel_flags= OFDM+5GHz
  dbm_antsignal= -84
  antenna   = 0
  rx_flags  = 
  notdecoded= ''

Also compare integer value of r.present:

  • 793247744 on big endian system
  • 18479 on little endian
struct.unpack('<I',struct.pack('>I', 793247744))[0] == 18479

clearly seems to be endian related.

Can somebody point me to the likely source of this issue?

Many thanks for all your work on scapy.

matt7aylor avatar Jul 19 '17 21:07 matt7aylor

It will work on the big endian system if I do the following dodgy hack to reverse the order of bytes for the FlagsField (obviously this is going to break little endian systems and probably a bunch of other stuff too).

--- a/scapy/fields.py
+++ b/scapy/fields.py
@@ -693,6 +693,7 @@ class BitField(Field):
 
         # split the substring byte by byte
         bs = struct.unpack('!%dB' % nb_bytes , w)
+        bs = b[::-1]
 
         b = 0
         for c in range(nb_bytes):

matt7aylor avatar Jul 19 '17 23:07 matt7aylor

Ok, the problem seems to be with the reverse function for the BitField class, on a big endian system the socket.ntohl/socket.ntohs functions don't actually reverse the bytes so nothing happens, changing to a more manual method using struct seems to fix the problem:

--- a/scapy/fields.py
+++ b/scapy/fields.py
@@ -657,9 +657,9 @@ class BitField(Field):
         self.size = abs(size)
     def reverse(self, val):
         if self.size == 16:
-            val = socket.ntohs(val)
+            val = struct.unpack('>H',struct.pack('<H', val))[0]
         elif self.size == 32:
-            val = socket.ntohl(val)
+            val = struct.unpack('>I',struct.pack('<I', val))[0]
         return val
         
     def addfield(self, pkt, s, val):

Sorry for the multiple comment spam (didn't realise I would find as much myself), hopefully the above, or something like it, will fix this issue.

matt7aylor avatar Jul 20 '17 07:07 matt7aylor

Great, you found the solution. Can you prepare a pull request? A test case (going into regression.uts) would, also, be nice.

phaethon avatar Jul 20 '17 07:07 phaethon