Repository: secdev/scapy

Issue:
macOS VMWare Fusion with long interface name
#### Brief description

Unable to get scapy to work on macOS Big Sur when using UDP raw sockets like `sr1(IP(dst="192.168.43.5")/UDP(sport=137, dport=137))` to a VMWare Fusion VM on interface bridge100. The interface is truncated to bridge1 which does not exist.

This was discussed in gitter and I am filing an official ticket. It may be a Big Sur/Python error and not related to scapy.

https://gitter.im/secdev/scapy?at=5fff2bbcdc2e4809aa1daa7f

#### Environment

```
% pip list | grep scapy
scapy                  2.4.4.dev265
% sudo python --version
Python 3.8.1
% uname -a
Darwin User-MBP 20.2.0 Darwin Kernel Version 20.2.0: Wed Dec  2 20:39:59 PST 2020; root:xnu-7195.60.75~1/RELEASE_X86_64 x86_64
% sw_vers 
ProductName:	macOS
ProductVersion:	11.1
BuildVersion:	20C69
```

libpcap was installed via homebrew
```
% brew list libpcap
/usr/local/Cellar/libpcap/1.9.1/bin/pcap-config
/usr/local/Cellar/libpcap/1.9.1/include/pcap/ (15 files)
/usr/local/Cellar/libpcap/1.9.1/include/ (3 files)
/usr/local/Cellar/libpcap/1.9.1/lib/libpcap.1.9.1.dylib
/usr/local/Cellar/libpcap/1.9.1/lib/pkgconfig/libpcap.pc
/usr/local/Cellar/libpcap/1.9.1/lib/ (3 other files)
/usr/local/Cellar/libpcap/1.9.1/share/man/ (79 files)
% echo $LDFLAGS 
-L/usr/local/opt/libffi/lib -L/usr/local/opt/libpcap/lib
% echo $CPPFLAGS
-I/usr/local/opt/libpcap/include
% echo $PATH | awk '{split($0,a,":"); print a[1]}'          
/usr/local/opt/libpcap/bin
```

#### How to reproduce
192.168.43.5 is a Windows XP box on VMWare Fusion with 'Share with my Mac' networking selected
```
% scapy
>>> scapy.__version__
'2.4.4.dev265'
>>> conf.use_pcap
False
>>> pkt = sr1(IP(dst="192.168.43.5")/UDP(sport=137, dport=137), timeout=2, verbose=0)
Traceback (most recent call last):
  File "/Users/user/.pyenv/versions/3.8.1/lib/python3.8/site-packages/scapy/arch/bpf/supersocket.py", line 73, in __init__
    fcntl.ioctl(self.ins, BIOCSETIF, struct.pack("16s16x", self.iface.encode()))  # noqa: E501
OSError: [Errno 6] Device not configured

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/user/.pyenv/versions/3.8.1/lib/python3.8/site-packages/scapy/sendrecv.py", line 541, in sr1
    s = conf.L3socket(promisc=promisc, filter=filter,
  File "/Users/user/.pyenv/versions/3.8.1/lib/python3.8/site-packages/scapy/arch/bpf/supersocket.py", line 241, in __init__
    super(L2bpfListenSocket, self).__init__(*args, **kwargs)
  File "/Users/user/.pyenv/versions/3.8.1/lib/python3.8/site-packages/scapy/arch/bpf/supersocket.py", line 75, in __init__
    raise Scapy_Exception("BIOCSETIF failed on %s" % self.iface)
scapy.error.Scapy_Exception: BIOCSETIF failed on bridge1
>>> conf.use_pcap = True
WARNING: No libpcap provider available ! pcap won't be used
>>> pkt = sr1(IP(dst="192.168.43.5")/UDP(sport=137, dport=137), timeout=2, verbose=0)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/user/.pyenv/versions/3.8.1/lib/python3.8/site-packages/scapy/sendrecv.py", line 541, in sr1
    s = conf.L3socket(promisc=promisc, filter=filter,
  File "/Users/user/.pyenv/versions/3.8.1/lib/python3.8/site-packages/scapy/supersocket.py", line 273, in __init__
    self.outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)  # noqa: E501
  File "/Users/user/.pyenv/versions/3.8.1/lib/python3.8/socket.py", line 231, in __init__
    _socket.socket.__init__(self, family, type, proto, fileno)
PermissionError: [Errno 1] Operation not permitted
```

```
% sudo scapy
>>> conf.use_pcap
False
>>> scapy.__version__
'2.4.4.dev265'
>>> pkt = sr1(IP(pkt = sr1(IP(dst="192.168.43.5")/UDP(sport=137, dport=137), timeout=2, verbose=1)
Traceback (most recent call last):
  File "/Users/user/.pyenv/versions/3.8.1/lib/python3.8/site-packages/scapy/arch/bpf/supersocket.py", line 73, in __init__
    fcntl.ioctl(self.ins, BIOCSETIF, struct.pack("16s16x", self.iface.encode()))  # noqa: E501
OSError: [Errno 6] Device not configured

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/user/.pyenv/versions/3.8.1/lib/python3.8/site-packages/scapy/sendrecv.py", line 541, in sr1
    s = conf.L3socket(promisc=promisc, filter=filter,
  File "/Users/user/.pyenv/versions/3.8.1/lib/python3.8/site-packages/scapy/arch/bpf/supersocket.py", line 241, in __init__
    super(L2bpfListenSocket, self).__init__(*args, **kwargs)
  File "/Users/user/.pyenv/versions/3.8.1/lib/python3.8/site-packages/scapy/arch/bpf/supersocket.py", line 75, in __init__
    raise Scapy_Exception("BIOCSETIF failed on %s" % self.iface)
scapy.error.Scapy_Exception: BIOCSETIF failed on bridge1
>>> conf.use_pcap=True
WARNING: No libpcap provider available ! pcap won't be used
>>> pkt = sr1(IP(dst="192.168.43.5")/UDP(sport=137, dport=137), timeout=2, verbose=1)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/user/.pyenv/versions/3.8.1/lib/python3.8/site-packages/scapy/sendrecv.py", line 541, in sr1
    s = conf.L3socket(promisc=promisc, filter=filter,
  File "/Users/user/.pyenv/versions/3.8.1/lib/python3.8/site-packages/scapy/supersocket.py", line 275, in __init__
    self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))  # noqa: E501
AttributeError: module 'socket' has no attribute 'AF_PACKET'


Discussion:
I just checked and I don't have any issue on Big Sur with the master branch. It seems that pip report 2.4.4 while your are testing against '2.4.4.dev265'.

Could you try with the following commands?
```
git clone --depth=1 https://github.com/secdev/scapy
cd scapy/
sudo ./run_scapy
>>> sr1(IP(dst="1.1.1.1")/ICMP())
```

Please try with `sr1(IP(dst="192.168.43.5")/UDP(sport=137, dport=137))`
Please answer my question.
Your above code snippet works but `sr1(IP(dst="192.168.43.5")/UDP(sport=137, dport=137))` does not. 

```
>>> sr1(IP(dst="1sr1(IP(dst="1.1.1.1")/ICMP())
Begin emission:
Finished sending 1 packets.
...*
Received 4 packets, got 1 answers, remaining 0 packets
<IP  version=4 ihl=5 tos=0x0 len=28 id=36898 flags= frag=0 ttl=55 proto=icmp chksum=0x2fc5 src=1.1.1.1 dst=192.168.1.80 |<ICMP  type=echo-reply code=0 chksum=0x0 id=0x0 seq=0x0 |>>
```

```
sr1(IP(dst="1.1.1.1")/UDP(sport=137, dport=137))
```

Does not give the exception - only 192.168.43.5
I stand by what I said in https://gitter.im/secdev/scapy?at=5fc8ef055a3e9845cd6d2d00 (as you pointed out). We probably shouldn't even bother with BigSur < Py3.9.1 issues.

https://www.python.org/downloads/release/python-391/


> Installer news
> 3.9.1 is the first version of Python to support macOS 11 Big Sur.


master does not have any issue on Big Sur with Python 3.9.1 installed with Homebrew:
```
>>> sys.version
'3.9.1 (default, Dec 29 2020, 08:52:17) \n[Clang 12.0.0 (clang-1200.0.32.28)]'
>>> sr1(IP(dst="1.1.1.1") / UDP() / DNS(qd=DNSQR()))
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
<IP  version=4 ihl=5 tos=0x0 len=77 id=42108 flags=DF frag=0 ttl=57 proto=udp chksum=0xb04e src=1.1.1.1 dst=192.168.42.43 |<UDP  sport=domain dport=domain len=57 chksum=0x344 |<DNS  id=0 qr=1 opcode=QUERY aa=0 tc=0 rd=1 ra=1 z=0 ad=0 cd=0 rcode=ok qdcount=1 ancount=1 nscount=0 arcount=0 qd=<DNSQR  qname='www.example.com.' qtype=A qclass=IN |> an=<DNSRR  rrname='www.example.com.' type=A rclass=IN ttl=75093 rdlen=None rdata=93.184.216.34 |> ns=None ar=None |>>>
```

It also works fine with the Python 2.7 and 3.8.2 installed with Big Sur.
I believe the original issue may have been misdiagnosed. It may be a VMware Fusion issue as it seems to only effect the VM bridge interface. This is in Python 3.8 and 3.9.1

```
>>> import sys
>>> sys.version
'3.9.1 (default, Jan 14 2021, 14:05:22) \n[Clang 12.0.0 (clang-1200.0.32.28)]'
>>> scapy.__version__
'a436560'
>>> sr1(IP(dst="1sr1(IP(dst="1.1.1.1")/UDP(sport=137, dport=137))
Begin emission:
Finished sending 1 packets.
......................................................................................................................................................................^C
Received 166 packets, got 0 answers, remaining 1 packets
>>> sr1(IP(dst="192.168.43.5")/UDP(sport=137, dport=137))
Traceback (most recent call last):
  File "/Users/user/Development/scapy/scapy/arch/bpf/supersocket.py", line 73, in __init__
    fcntl.ioctl(self.ins, BIOCSETIF, struct.pack("16s16x", self.iface.encode()))  # noqa: E501
OSError: [Errno 6] Device not configured

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/user/Development/scapy/scapy/sendrecv.py", line 541, in sr1
    s = conf.L3socket(promisc=promisc, filter=filter,
  File "/Users/user/Development/scapy/scapy/arch/bpf/supersocket.py", line 241, in __init__
    super(L2bpfListenSocket, self).__init__(*args, **kwargs)
  File "/Users/user/Development/scapy/scapy/arch/bpf/supersocket.py", line 75, in __init__
    raise Scapy_Exception("BIOCSETIF failed on %s" % self.iface)
scapy.error.Scapy_Exception: BIOCSETIF failed on bridge1
```

Using libpcap is fixed in 3.9.1 but it seems the base issue is still present.
```
>>> conf.use_pcap = True
WARNING: No IPv4 address found on ap1 !
WARNING: No IPv4 address found on en3 !
WARNING: more No IPv4 address found on en4 !
>>> sr1(IP(dst="192.168.43.5")/UDP(sport=137, dport=137))
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/user/Development/scapy/scapy/sendrecv.py", line 541, in sr1
    s = conf.L3socket(promisc=promisc, filter=filter,
  File "/Users/user/Development/scapy/scapy/arch/libpcap.py", line 421, in __init__
    self.ins = open_pcap(iface, MTU, self.promisc, 100,
  File "/Users/user/Development/scapy/scapy/arch/libpcap.py", line 261, in __init__
    raise OSError(error)
OSError: b'bridge1: No such device exists (BIOCSETIF failed: Device not configured)'
```

Perhaps related but I don't have a bridge1 when I do an ifconfig. I have a bridge0 and a bridge100. I do not know the inner workings on VMWare Fusion too well or bridged networking so I am unable to determine the next steps forward.

```
>>> get_if_list()
['lo0', 'ap1', 'en0', 'en3', 'en4', 'en1', 'en2', 'bridge0', 'awdl0', 'llw0', 'en5', 'en7', 'bridge100', 'en9']
>>> conf.ifaces
Source  Index  Name       MAC                IPv4          IPv6                     
BPF     1      lo0        00:00:00:00:00:00  127.0.0.1     ::1                      
                                                           fe80::1                  
BPF     10     en1        82:41:9b:01:34:01  0.0.0.0                                
BPF     11     en2        82:41:9b:01:34:00  0.0.0.0                                
BPF     12     bridge0    82:41:9b:01:34:01  0.0.0.0                                
BPF     13     awdl0      36:d7:dc:5a:54:74  0.0.0.0       fe80::34d7:dcff:fe5a:5474
BPF     14     llw0       36:d7:dc:5a:54:74  0.0.0.0       fe80::34d7:dcff:fe5a:5474
BPF     18     en7        1e:74:18:0a:87:73  0.0.0.0                                
BPF     19     bridge100  fa:ff:c2:70:a0:64  192.168.43.1  fe80::1cf4:5d2d:fccc:7ce 
BPF     20     en9        8a:de:f3:a7:76:1f  0.0.0.0                                
BPF     6      en0        Apple:07:99:39     10.2.2.245    fe80::18b4:4fca:9266:1574
BPF     8      en3        82:41:9b:01:34:05  0.0.0.0                                
BPF     9      en4        82:41:9b:01:34:04  0.0.0.0                                
>>> conf.route
Network          Netmask          Gateway   Iface    Output IP   Metric
0.0.0.0          0.0.0.0          10.2.2.1  en0      10.2.2.245  1     
0.0.0.0          0.0.0.0          0.0.0.0   bridge1  0.0.0.0     1     
10.2.2.0         255.255.255.0    0.0.0.0   en0      10.2.2.245  1     
10.2.2.1         255.255.255.255  0.0.0.0   en0      10.2.2.245  1     
10.2.2.1         255.255.255.255  0.0.0.0   en0      10.2.2.245  1     
10.2.2.144       255.255.255.255  0.0.0.0   en0      10.2.2.245  1     
10.2.2.193       255.255.255.255  0.0.0.0   en0      10.2.2.245  1     
10.2.2.245       255.255.255.255  0.0.0.0   en0      10.2.2.245  1     
127.0.0.0        255.0.0.0        0.0.0.0   lo0      127.0.0.1   1     
127.0.0.1        255.255.255.255  0.0.0.0   lo0      127.0.0.1   1     
169.254.0.0      255.255.0.0      0.0.0.0   en0      10.2.2.245  1     
192.168.43.0     255.255.255.0    0.0.0.0   bridge1  0.0.0.0     1     
192.168.43.5     255.255.255.255  0.0.0.0   bridge1  0.0.0.0     1     
224.0.0.0        240.0.0.0        0.0.0.0   en0      10.2.2.245  1     
224.0.0.251      255.255.255.255  0.0.0.0   en0      10.2.2.245  1     
255.255.255.255  255.255.255.255  0.0.0.0   en0      10.2.2.245  1 
>>> conf.route.route('192.168.43.5')
('bridge1', '0.0.0.0', '0.0.0.0')
>>> resolve_iface("bridge100")
<NetworkInterface bridge100 [UP+BROADCAST+NOTRAILERS+RUNNING+NOTRAILERS+MASTER+AUTOMEDIA]>
>>> resolve_iface("bridge1")
<NetworkInterface bridge1 [dummy]>
```

[`netstat -rn -f inet`](https://github.com/secdev/scapy/blob/8d6f1dac47458d7e27ab49277cac424334a9248c/scapy/arch/unix.py#L63) is incorrect as the interface name is cut off?
Could you share the output of `netstat -rn -f inet` and `netstat -rnW -f inet` ?
get_if_addr https://github.com/secdev/scapy/blob/8d6f1dac47458d7e27ab49277cac424334a9248c/scapy/arch/unix.py#L120 which calls get_if_raw_addr https://github.com/secdev/scapy/blob/8d6f1dac47458d7e27ab49277cac424334a9248c/scapy/arch/bpf/core.py#L74 doesn't raise an OSError so _guess_iface_name https://github.com/secdev/scapy/blob/8d6f1dac47458d7e27ab49277cac424334a9248c/scapy/arch/unix.py#L127 is never called

```
% netstat -rn -f inet
Routing tables

Internet:
Destination        Gateway            Flags        Netif Expire
default            10.2.2.1           UGSc           en0       
default            link#19            UCSI       bridge1      !
10.2.2/24          link#6             UCS            en0      !
10.2.2.1/32        link#6             UCS            en0      !
10.2.2.1           18:e8:29:bd:7f:4f  UHLWIir        en0   1169
10.2.2.144         8:66:98:e1:40:f1   UHLWI          en0   1054
10.2.2.231         b8:27:eb:ba:39:f6  UHLWI          en0    947
10.2.2.245/32      link#6             UCS            en0      !
127                127.0.0.1          UCS            lo0       
127.0.0.1          127.0.0.1          UH             lo0       
169.254            link#6             UCS            en0      !
192.168.43         link#19            UCS        bridge1      !
192.168.43.5       0.c.29.d8.f6.86    UHLWI      bridge1    558
224.0.0/4          link#6             UmCS           en0      !
224.0.0.251        1:0:5e:0:0:fb      UHmLWI         en0       
255.255.255.255/32 link#6             UCS            en0      !
```

```
% netstat -rnW -f inet
Routing tables

Internet:
Destination        Gateway            Flags        Netif Expire
default            10.2.2.1           UGSc           en0       
default            link#19            UCSI       bridge1      !
10.2.2/24          link#6             UCS            en0      !
10.2.2.1/32        link#6             UCS            en0      !
10.2.2.1           18:e8:29:bd:7f:4f  UHLWIir        en0   1197
10.2.2.144         8:66:98:e1:40:f1   UHLWI          en0   1035
10.2.2.231         b8:27:eb:ba:39:f6  UHLWI          en0    928
10.2.2.245/32      link#6             UCS            en0      !
127                127.0.0.1          UCS            lo0       
127.0.0.1          127.0.0.1          UH             lo0       
169.254            link#6             UCS            en0      !
192.168.43         link#19            UCS        bridge1      !
192.168.43.5       0.c.29.d8.f6.86    UHLWI      bridge1    539
224.0.0/4          link#6             UmCS           en0      !
224.0.0.251        1:0:5e:0:0:fb      UHmLWI         en0       
255.255.255.255/32 link#6             UCS            en0      !
```

Sadly, `-W` doesn't seem to be very helpful

```
% netstat -nr
Routing tables

Internet:
Destination        Gateway            Flags        Netif Expire
default            10.2.2.1           UGSc           en0       
default            link#19            UCSI       bridge1      !
10.2.2/24          link#6             UCS            en0      !
10.2.2.1/32        link#6             UCS            en0      !
10.2.2.1           18:e8:29:bd:7f:4f  UHLWIir        en0   1185
10.2.2.144         8:66:98:e1:40:f1   UHLWI          en0   1191
10.2.2.231         b8:27:eb:ba:39:f6  UHLWI          en0    783
10.2.2.245/32      link#6             UCS            en0      !
127                127.0.0.1          UCS            lo0       
127.0.0.1          127.0.0.1          UH             lo0       
169.254            link#6             UCS            en0      !
192.168.43         link#19            UCS        bridge1      !
192.168.43.5       0.c.29.d8.f6.86    UHLWI      bridge1    394
224.0.0/4          link#6             UmCS           en0      !
224.0.0.251        1:0:5e:0:0:fb      UHmLWI         en0       
255.255.255.255/32 link#6             UCS            en0      !

Internet6:
Destination                             Gateway                         Flags         Netif Expire
default                                 fe80::%utun0                    UGcI          utun0       
default                                 fe80::%utun1                    UGcI          utun1       
::1                                     ::1                             UHL             lo0       
fe80::%lo0/64                           fe80::1%lo0                     UcI             lo0       
fe80::1%lo0                             link#1                          UHLI            lo0       
fe80::%en5/64                           link#5                          UCI             en5       
fe80::aede:48ff:fe00:1122%en5           ac:de:48:0:11:22                UHLI            lo0       
fe80::aede:48ff:fe33:4455%en5           ac:de:48:33:44:55               UHLWIi          en5       
fe80::%en0/64                           link#6                          UCI             en0       
fe80::18b4:4fca:9266:1574%en0           f8:ff:c2:7:99:39                UHLI            lo0       
fe80::%awdl0/64                         link#13                         UCI           awdl0       
fe80::34d7:dcff:fe5a:5474%awdl0         36:d7:dc:5a:54:74               UHLI            lo0       
fe80::%llw0/64                          link#14                         UCI            llw0       
fe80::34d7:dcff:fe5a:5474%llw0          36:d7:dc:5a:54:74               UHLI            lo0       
fe80::6361:a918:4da5:a015%utun0         link#15                         UHLI            lo0       
fe80::66e8:5f0f:3bd7:1cb1%utun1         link#16                         UHLI            lo0       
fe80::%bridge100/64                     link#19                         UCSI       bridge10       
fe80::1cf4:5d2d:fccc:7ce%bridge100      fa.ff.c2.70.a0.64               UHLI            lo0       
ff00::/8                                ::1                             UmCI            lo0       
ff00::/8                                link#5                          UmCI            en5       
ff00::/8                                link#6                          UmCI            en0       
ff00::/8                                link#13                         UmCI          awdl0       
ff00::/8                                link#14                         UmCI           llw0       
ff00::/8                                link#19                         UmCI       bridge10       
ff01::%lo0/32                           ::1                             UmCI            lo0       
ff01::%en5/32                           link#5                          UmCI            en5       
ff01::%en0/32                           link#6                          UmCI            en0       
ff01::%awdl0/32                         link#13                         UmCI          awdl0       
ff01::%llw0/32                          link#14                         UmCI           llw0       
ff01::%bridge100/32                     link#19                         UmCSI      bridge10       
ff02::%lo0/32                           ::1                             UmCI            lo0       
ff02::%en5/32                           link#5                          UmCI            en5       
ff02::%en0/32                           link#6                          UmCI            en0       
ff02::%awdl0/32                         link#13                         UmCI          awdl0       
ff02::%llw0/32                          link#14                         UmCI           llw0       
ff02::%bridge100/32                     link#19                         UmCI       bridge10  
```

Filed a radar. #FB8970671
Thanks for sharing! I am able to reproduce the issue with 10.14 using the following commands:
```
ifconfig bridge100 create
ifconfig bridge100 172.16.1.2/24 up
./run_scapy
>>> sr1(IP(dst="172.16.1.2", src="172.16.1.1") / ICMP())
Traceback (most recent call last):
[..]
scapy.error.Scapy_Exception: BIOCSETIF failed on bridge1
```

I am working on a fix.
Isn't there a way to not use `netstat` on OSX?
This is indeed a regression that was already fixed, but is again broken. The culprit call is mocked that why the test never broke.

Sent from my iPhone

> On 18 Jan 2021, at 12:10, Gabriel <notifications@github.com> wrote:
> 
> ﻿
> Isn't there a way to not use netstat on OSX?
> 
> —
> You are receiving this because you commented.
> Reply to this email directly, view it on GitHub, or unsubscribe.

On Python 3.3+ [`if_nameindex`](https://docs.python.org/3/library/socket.html#socket.if_nameindex) works on my MacBook Pro to get a list of the network interfaces.
We [already use it](https://github.com/secdev/scapy/blob/db89d7b183b90c4f6dd6fcad577102d3be567d03/scapy/arch/bpf/core.py#L160), the issue here is getting the IPv4 and IPv6 routes.

Resolving patch:
diff --git a/scapy/arch/bpf/core.py b/scapy/arch/bpf/core.py
--- a/scapy/arch/bpf/core.py
+++ b/scapy/arch/bpf/core.py
@@ -70,10 +70,10 @@ def get_if_raw_addr(ifname):
     )
     stdout, stderr = subproc.communicate()
     if subproc.returncode:
-        warning("Failed to execute ifconfig: (%s)", plain_str(stderr))
+        warning("Failed to execute ifconfig: (%s)", plain_str(stderr).strip())
         return b"\0\0\0\0"
-    # Get IPv4 addresses
 
+    # Get IPv4 addresses
     addresses = [
         line.strip() for line in plain_str(stdout).splitlines()
         if "inet " in line
@@ -108,7 +108,7 @@ def get_if_raw_hwaddr(ifname):
     stdout, stderr = subproc.communicate()
     if subproc.returncode:
         raise Scapy_Exception("Failed to execute ifconfig: (%s)" %
-                              (plain_str(stderr)))
+                              plain_str(stderr).strip())
 
     # Get MAC addresses
     addresses = [
diff --git a/scapy/arch/unix.py b/scapy/arch/unix.py
--- a/scapy/arch/unix.py
+++ b/scapy/arch/unix.py
@@ -118,23 +118,22 @@ def read_routes():
             from scapy.arch import get_if_addr
             try:
                 ifaddr = get_if_addr(netif)
-                routes.append((dest, netmask, gw, netif, ifaddr, metric))
-            except OSError as exc:
-                if 'Device not configured' in str(exc):
+                if ifaddr == "0.0.0.0":
                     # This means the interface name is probably truncated by
                     # netstat -nr. We attempt to guess it's name and if not we
                     # ignore it.
                     guessed_netif = _guess_iface_name(netif)
                     if guessed_netif is not None:
                         ifaddr = get_if_addr(guessed_netif)
-                        routes.append((dest, netmask, gw, guessed_netif, ifaddr, metric))  # noqa: E501
+                        netif = guessed_netif
                     else:
                         log_runtime.info(
                             "Could not guess partial interface name: %s",
                             netif
                         )
-                else:
-                    raise
+                routes.append((dest, netmask, gw, netif, ifaddr, metric))
+            except OSError:
+                raise
         else:
             pending_if.append((dest, netmask, gw))
     f.close()


Test patch:
diff --git a/test/regression.uts b/test/regression.uts
--- a/test/regression.uts
+++ b/test/regression.uts
@@ -2312,7 +2312,7 @@ default            link#11            UCSI            1        0 bridge1
     def se_get_if_addr(iface):
         """Perform specific side effects"""
         if iface == "bridge1":
-            raise OSError("Device not configured")
+            return "0.0.0.0"
         return "1.2.3.4"
     mock_get_if_addr.side_effect = se_get_if_addr
     # Test the function
@@ -2449,9 +2449,10 @@ test_osx_10_15_ipv4()
 import mock
 from io import StringIO
 
+@mock.patch("scapy.arch.get_if_addr")
 @mock.patch("scapy.arch.unix.OPENBSD")
 @mock.patch("scapy.arch.unix.os")
-def test_openbsd_6_3(mock_os, mock_openbsd):
+def test_openbsd_6_3(mock_os, mock_openbsd, mock_get_if_addr):
     """Test read_routes() on OpenBSD 6.3"""
     # 'netstat -rn -f inet' output
     netstat_output = u"""
@@ -2481,6 +2482,16 @@ default            10.0.1.254         UGS        0        0     -     8 bge0
     
     # Mocked OpenBSD parsing behavior
     mock_openbsd = True
+    
+    # Mocked get_if_addr() output
+    def se_get_if_addr(iface):
+        """Perform specific side effects"""
+        import socket
+        if iface == "bge0":
+            return "192.168.122.42"
+        return "10.0.1.26"
+    mock_get_if_addr.side_effect = se_get_if_addr
+    
     # Test the function
     from scapy.arch.unix import read_routes
     return read_routes()
@@ -2510,9 +2521,10 @@ from io import StringIO
 
 # Mocked Solaris 11.1 parsing behavior
 
+@mock.patch("scapy.arch.get_if_addr")
 @mock.patch("scapy.arch.unix.SOLARIS", True)
 @mock.patch("scapy.arch.unix.os")
-def test_solaris_111(mock_os):
+def test_solaris_111(mock_os, mock_get_if_addr):
     """Test read_routes() on Solaris 11.1"""
     # 'netstat -rvn -f inet' output
     netstat_output = u"""
@@ -2528,6 +2540,15 @@ default              0.0.0.0         10.0.2.2             net0    1500   2 UG
     mock_os.popen = mock.MagicMock(return_value=strio)
     print(scapy.arch.unix.SOLARIS)
     
+    # Mocked get_if_addr() output
+    def se_get_if_addr(iface):
+        """Perform specific side effects"""
+        import socket
+        if iface == "net0":
+            return "10.0.2.15"
+        return "127.0.0.1"
+    mock_get_if_addr.side_effect = se_get_if_addr
+    
     # Test the function
     from scapy.arch.unix import read_routes
     return read_routes()
@@ -2849,9 +2870,10 @@ test_freebsd_10_2()
 
 import mock
 from io import StringIO
-
+ 
+@mock.patch("scapy.arch.get_if_addr")
 @mock.patch("scapy.arch.unix.os")
-def test_freebsd_13(mock_os):
+def test_freebsd_13(mock_os, mock_get_if_addr):
     """Test read_routes() on FreeBSD 13"""
     # 'netstat -rnW -f inet' output
     netstat_output = u"""
@@ -2867,6 +2889,13 @@ default            10.0.0.1           UGS         3   1500     vtnet0
     # Mocked file descriptor
     strio = StringIO(netstat_output)
     mock_os.popen = mock.MagicMock(return_value=strio)
+    # Mocked get_if_addr() behavior
+    def se_get_if_addr(iface):
+        """Perform specific side effects"""
+        if iface == "vtnet0":
+            return "10.0.0.1"
+        return "1.2.3.4"
+    mock_get_if_addr.side_effect = se_get_if_addr
     # Test the function
     from scapy.arch.unix import read_routes
     routes = read_routes()