Repository: secdev/scapy

Issue:
X86_64 is incorrect when running a 32bit binary under 64bit machine
I packed my program by PyInstaller under 32bit python.  When run it under 64bit machine. Got the following error:
```
  File "scapy/sendrecv.py", line 593, in sniff
  File "scapy/arch/linux.py", line 496, in __init__
  File "scapy/arch/linux.py", line 157, in attach_filter
  File "socket.py", line 224, in meth
socket.error: [Errno 22] Invalid argument
```
I checked the source code of scapy,  the X86_64 is set to True, cause a wrong offset for the BPF in attach_filter is set .  

In this case,  I think the program should treat the runtime platform totally as a 32bit platform.

I googled this issue and find some old issues are filed several years ago. But obviously, it has not get resolved.
https://bitbucket.org/secdev/scapy/issues/486/scapy-misdetects-the-current-architecture
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=594261

Here is the patch for X86 platform:
```
file: scapy/arch/consts.py
@@ -5,6 +5,7 @@

 import os
 from sys import platform
+import platform as pf

 LINUX = platform.startswith("linux")
 OPENBSD = platform.startswith("openbsd")
@@ -20,7 +21,8 @@
     ARM_64 = False
 else:
     uname = os.uname()
-    X86_64 = uname[4] == 'x86_64'
+    X86_64 = pf.architecture()[0] == '64bit'
     ARM_64 = uname[4] == 'aarch64'

 LOOPBACK_NAME = "lo" if LINUX else "lo0"
```




Discussion:
Sounds good to me. Care to submit a pull request?
@p-l- I guess this can be added manually...

Resolving patch:
diff --git a/scapy/arch/__init__.py b/scapy/arch/__init__.py
--- a/scapy/arch/__init__.py
+++ b/scapy/arch/__init__.py
@@ -10,7 +10,7 @@
 import socket
 
 from scapy.consts import LINUX, OPENBSD, FREEBSD, NETBSD, DARWIN, \
-    SOLARIS, WINDOWS, BSD, X86_64, ARM_64, LOOPBACK_NAME, plt, MATPLOTLIB_INLINED, \
+    SOLARIS, WINDOWS, BSD, IS_64BITS, LOOPBACK_NAME, plt, MATPLOTLIB_INLINED, \
     MATPLOTLIB_DEFAULT_PLOT_KARGS, PYX, parent_function
 from scapy.error import *
 import scapy.config
diff --git a/scapy/arch/linux.py b/scapy/arch/linux.py
--- a/scapy/arch/linux.py
+++ b/scapy/arch/linux.py
@@ -11,7 +11,7 @@
 from select import select
 from fcntl import ioctl
 
-from scapy.consts import LOOPBACK_NAME
+from scapy.consts import LOOPBACK_NAME, IS_64BITS
 import scapy.utils
 import scapy.utils6
 from scapy.packet import Packet, Padding
@@ -149,10 +149,7 @@ def attach_filter(s, bpf_filter, iface):
 
     # XXX. Argl! We need to give the kernel a pointer on the BPF,
     # python object header seems to be 20 bytes. 36 bytes for x86 64bits arch.
-    if scapy.arch.X86_64 or scapy.arch.ARM_64:
-        bpfh = struct.pack("HL", nb, id(bpf)+36)
-    else:
-        bpfh = struct.pack("HI", nb, id(bpf)+20)  
+    bpfh = struct.pack("HL", nb, id(bpf) + (36 if IS_64BITS else 20))
     s.setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, bpfh)
 
 def set_promisc(s,iff,val=1):
diff --git a/scapy/consts.py b/scapy/consts.py
--- a/scapy/consts.py
+++ b/scapy/consts.py
@@ -4,7 +4,7 @@
 ## This program is published under a GPLv2 license
 
 import os, inspect
-from sys import platform
+from sys import platform, maxsize
 import platform as platform_lib
 from scapy.error import *
 
@@ -40,10 +40,10 @@
 SOLARIS = platform.startswith("sunos")
 WINDOWS = platform.startswith("win32")
 BSD = DARWIN or FREEBSD or OPENBSD or NETBSD
+# See https://docs.python.org/3/library/platform.html#cross-platform
+IS_64BITS = maxsize > 2**32
 
 if WINDOWS:
-    X86_64 = False
-    ARM_64 = False
     try:
         if float(platform_lib.release()) >= 8.1:
             LOOPBACK_NAME = "Microsoft KM-TEST Loopback Adapter"
@@ -53,8 +53,6 @@
         LOOPBACK_NAME = "Microsoft Loopback Adapter"
 else:
     uname = os.uname()
-    X86_64 = uname[4] == 'x86_64'
-    ARM_64 = uname[4] == 'aarch64'
     LOOPBACK_NAME = "lo" if LINUX else "lo0"
 
 def parent_function():


Test patch: