Skip to content
Snippets Groups Projects
Commit 02ae08b4 authored by Guillaume Valadon's avatar Guillaume Valadon Committed by Pierre Lalet
Browse files

Workaround to ignore interfaces name truncated by netstat

When interface names are longer than 7 characters, netstat will truncate
them to the first 7 chars which leads to looking up an invalid interface
name.
We attempt to guess the name of the interface based on the output of
ifconfig -l. If there is only one candidate we consider it, otherwise we
ignore it.
parent 004b9f8c
No related branches found
No related tags found
No related merge requests found
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
Common customizations for all Unix-like operating systems other than Linux Common customizations for all Unix-like operating systems other than Linux
""" """
from __future__ import with_statement
import sys,os,struct,socket,time import sys,os,struct,socket,time
from fcntl import ioctl from fcntl import ioctl
import socket import socket
...@@ -24,6 +26,21 @@ from scapy.config import conf ...@@ -24,6 +26,21 @@ from scapy.config import conf
## Routes stuff ## ## Routes stuff ##
################## ##################
def _guess_iface_name(netif):
"""
We attempt to guess the name of interfaces that are truncated from the
output of ifconfig -l.
If there is only one possible candidate matching the interface name then we
return it.
If there are none or more, then we return None.
"""
with os.popen('%s -l' % conf.prog.ifconfig) as fdesc:
ifaces = fdesc.readline().strip().split(' ')
matches = [iface for iface in ifaces if iface.startswith(netif)]
if len(matches) == 1:
return matches[0]
return None
def read_routes(): def read_routes():
if scapy.arch.SOLARIS: if scapy.arch.SOLARIS:
...@@ -81,8 +98,22 @@ def read_routes(): ...@@ -81,8 +98,22 @@ def read_routes():
if not "G" in flg: if not "G" in flg:
gw = '0.0.0.0' gw = '0.0.0.0'
if netif is not None: if netif is not None:
try:
ifaddr = scapy.arch.get_if_addr(netif) ifaddr = scapy.arch.get_if_addr(netif)
routes.append((dest,netmask,gw,netif,ifaddr)) routes.append((dest,netmask,gw,netif,ifaddr))
except OSError as exc:
if exc.message == 'Device not configured':
# 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 = scapy.arch.get_if_addr(guessed_netif)
routes.append((dest, netmask, gw, guessed_netif, ifaddr))
else:
warning("Could not guess partial interface name: %s" % netif)
else:
raise
else: else:
pending_if.append((dest,netmask,gw)) pending_if.append((dest,netmask,gw))
f.close() f.close()
... ...
......
...@@ -4554,6 +4554,62 @@ assert isinstance(pkt, UDP) and pkt.dport == 5353 ...@@ -4554,6 +4554,62 @@ assert isinstance(pkt, UDP) and pkt.dport == 5353
pkt = pkt.payload pkt = pkt.payload
assert isinstance(pkt, DNS) and isinstance(pkt.payload, NoPayload) assert isinstance(pkt, DNS) and isinstance(pkt.payload, NoPayload)
+ Mocked read_routes() calls
= Truncated netstat -rn output on OS X
import mock
import StringIO
@mock.patch("scapy.arch.get_if_addr")
@mock.patch("scapy.arch.unix.os")
def test_osx_netstat_truncated(mock_os, mock_get_if_addr):
"""Test read_routes() on OS X 10.? with a long interface name"""
# netstat & ifconfig outputs from https://github.com/secdev/scapy/pull/119
netstat_output = """
Routing tables
Internet:
Destination Gateway Flags Refs Use Netif Expire
default 192.168.1.1 UGSc 460 0 en1
default link#11 UCSI 1 0 bridge1
127 127.0.0.1 UCS 1 0 lo0
127.0.0.1 127.0.0.1 UH 10 2012351 lo0
"""
ifconfig_output = "lo0 en1 bridge10\n"
# Mocked file descriptors
def se_popen(command):
"""Perform specific side effects"""
if command == "netstat -rn":
return StringIO.StringIO(netstat_output)
elif command == "ifconfig -l":
ret = StringIO.StringIO(ifconfig_output)
def unit():
return ret
ret.__call__ = unit
ret.__enter__ = unit
ret.__exit__ = lambda x,y,z: None
return ret
raise Exception("Command not mocked: %s" % command)
mock_os.popen.side_effect = se_popen
# Mocked get_if_addr() behavior
def se_get_if_addr(iface):
"""Perform specific side effects"""
if iface == "bridge1":
oserror_exc = OSError()
oserror_exc.message = "Device not configured"
raise oserror_exc
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()
assert(len(routes) == 4)
assert([r for r in routes if r[3] == "bridge10"])
test_osx_netstat_truncated()
+ Mocked read_routes6() calls + Mocked read_routes6() calls
= Preliminary definitions = Preliminary definitions
... ...
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment