secdev / scapy

Scapy: the Python-based interactive packet manipulation program & library.
https://scapy.net
GNU General Public License v2.0
10.76k stars 2.03k forks source link

socket.error: [Errno 99] Protocol not available on openwrt mips router #1013

Closed nicephil closed 6 years ago

nicephil commented 6 years ago

Bug Description

when I run the following example code on mips router, get the error as below

#! /usr/bin/env python
from scapy.all import *

def arp_monitor_callback(pkt):
    if ARP in pkt and pkt[ARP].op in (1,2): #who-has or is-at
        return pkt.sprintf("%ARP.hwsrc% %ARP.psrc%")

sniff(prn=arp_monitor_callback, filter="arp", store=0)

Error log:

WARNING: IPv6 support disabled in Python. Cannot load scapy IPv6 layers.
WARNING: can't import layer sctp: can't use AF_INET6, IPv6 is disabled
WARNING: can't import layer ipsec: can't use AF_INET6, IPv6 is disabled
Traceback (most recent call last):
  File "./dd.sh", line 8, in <module>
    sniff(prn=arp_monitor_callback, filter="arp", store=0)
  File "/usr/lib/python2.7/site-packages/scapy/sendrecv.py", line 561, in sniff
    s = L2socket(type=ETH_P_ALL, *arg, **karg)
  File "/usr/lib/python2.7/site-packages/scapy/arch/linux.py", line 471, in __init__
    attach_filter(self.ins, filter)
  File "/usr/lib/python2.7/site-packages/scapy/arch/linux.py", line 139, in attach_filter
    s.setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, bpfh) 
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 99] Protocol not available
root@UBNT-Pro /root [#]#

the error indicate the setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, bpfh) gets problem. I found SOL_SOCKET definition is different from linux header's. looks scapy only condiers x86 platform, but not all.

grep the linux macro definition as below:

alpha/include/asm/socket.h:8: * Note: we only bother about making the SOL_SOCKET options
alpha/include/asm/socket.h:13:#define SOL_SOCKET        0xffff
arm/include/asm/socket.h:7:#define SOL_SOCKET   1
avr32/include/asm/socket.h:7:#define SOL_SOCKET 1
cris/include/asm/socket.h:9:#define SOL_SOCKET  1
frv/include/asm/socket.h:7:#define SOL_SOCKET   1
h8300/include/asm/socket.h:7:#define SOL_SOCKET 1
ia64/include/asm/socket.h:16:#define SOL_SOCKET 1
m32r/include/asm/socket.h:7:#define SOL_SOCKET  1
m68k/include/asm/socket.h:7:#define SOL_SOCKET  1
mips/include/asm/socket.h:19:#define SOL_SOCKET 0xffff
mn10300/include/asm/socket.h:7:#define SOL_SOCKET       1
parisc/include/asm/socket.h:7:#define SOL_SOCKET        0xffff
powerpc/include/asm/socket.h:14:#define SOL_SOCKET      1
s390/include/asm/socket.h:15:#define SOL_SOCKET 1
sparc/include/asm/socket.h:7:#define SOL_SOCKET 0xffff
um/drivers/port_user.c:121:     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0) {
um/drivers/umcast_user.c:87:    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
um/os-Linux/drivers/tuntap_user.c:117:  if ((cmsg->cmsg_level != SOL_SOCKET) ||
um/os-Linux/file.c:494: if ((cmsg->cmsg_level != SOL_SOCKET) ||
xtensa/include/asm/socket.h:17:#define SOL_SOCKET       1

but scapy/arch/linux.py looks like:

# From bits/ioctls.h
SIOCGIFHWADDR  = 0x8927          # Get hardware address    
SIOCGIFADDR    = 0x8915          # get PA address          
SIOCGIFNETMASK = 0x891b          # get network PA mask     
SIOCGIFNAME    = 0x8910          # get iface name          
SIOCSIFLINK    = 0x8911          # set iface channel       
SIOCGIFCONF    = 0x8912          # get iface list          
SIOCGIFFLAGS   = 0x8913          # get flags               
SIOCSIFFLAGS   = 0x8914          # set flags               
SIOCGIFINDEX   = 0x8933          # name -> if_index mapping
SIOCGIFCOUNT   = 0x8938          # get number of devices
SIOCGSTAMP     = 0x8906          # get packet timestamp (as a timeval)

# From if.h
IFF_UP = 0x1               # Interface is up.
IFF_BROADCAST = 0x2        # Broadcast address valid.
IFF_DEBUG = 0x4            # Turn on debugging.
IFF_LOOPBACK = 0x8         # Is a loopback net.
IFF_POINTOPOINT = 0x10     # Interface is point-to-point link.
IFF_NOTRAILERS = 0x20      # Avoid use of trailers.
IFF_RUNNING = 0x40         # Resources allocated.
IFF_NOARP = 0x80           # No address resolution protocol.
IFF_PROMISC = 0x100        # Receive all packets.

# From netpacket/packet.h
PACKET_ADD_MEMBERSHIP  = 1
PACKET_DROP_MEMBERSHIP = 2
PACKET_RECV_OUTPUT     = 3
PACKET_RX_RING         = 5
PACKET_STATISTICS      = 6
PACKET_MR_MULTICAST    = 0
PACKET_MR_PROMISC      = 1
PACKET_MR_ALLMULTI     = 2

# From bits/socket.h
SOL_PACKET = 263
# From asm/socket.h
SO_ATTACH_FILTER = 26
SOL_SOCKET = 1          ######### here is different, why don't use socket.SOL_SOCKET?

# From net/route.h
RTF_UP = 0x0001  # Route usable
RTF_REJECT = 0x0200

# From if_packet.h
PACKET_HOST = 0  # To us
PACKET_BROADCAST = 1  # To all
PACKET_MULTICAST = 2  # To group
PACKET_OTHERHOST = 3  # To someone else
PACKET_OUTGOING = 4  # Outgoing of any type
PACKET_LOOPBACK = 5  # MC/BRD frame looped back
PACKET_USER = 6  # To user space
PACKET_KERNEL = 7  # To kernel space
PACKET_FASTROUTE = 6  # Fastrouted frame
# Unused, PACKET_FASTROUTE and PACKET_LOOPBACK are invisible to user space
gpotter2 commented 6 years ago

Hi ! On some systems, SOL_SOCKET is missing from socket. Would https://github.com/secdev/scapy/pull/1014 fix it for you ?

nicephil commented 6 years ago

it works. thanks.