Skip to content

Commit

Permalink
Cleanup get_if_raw_hwaddr where not useful
Browse files Browse the repository at this point in the history
  • Loading branch information
gpotter2 committed Aug 31, 2024
1 parent f4d9110 commit 429dbf1
Show file tree
Hide file tree
Showing 15 changed files with 78 additions and 99 deletions.
25 changes: 7 additions & 18 deletions scapy/arch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
from scapy.config import conf, _set_conf_sockets
from scapy.consts import LINUX, SOLARIS, WINDOWS, BSD
from scapy.data import (
ARPHDR_ETHER,
ARPHDR_LOOPBACK,
ARPHDR_PPP,
ARPHDR_TUN,
IPV6_ADDR_GLOBAL,
IPV6_ADDR_LOOPBACK,
)
from scapy.error import log_loading, Scapy_Exception
from scapy.interfaces import _GlobInterfaceType, network_name
from scapy.error import log_loading
from scapy.interfaces import (
_GlobInterfaceType,
network_name,
resolve_iface,
)
from scapy.pton_ntop import inet_pton, inet_ntop

from scapy.libs.extcap import load_extcap
Expand Down Expand Up @@ -50,7 +50,6 @@
"get_if_list",
"get_if_raw_addr",
"get_if_raw_addr6",
"get_if_raw_hwaddr",
"get_working_if",
"in6_getifaddr",
"read_nameservers",
Expand Down Expand Up @@ -89,12 +88,7 @@ def get_if_hwaddr(iff):
"""
Returns the MAC (hardware) address of an interface
"""
from scapy.arch import get_if_raw_hwaddr
addrfamily, mac = get_if_raw_hwaddr(iff) # noqa: F405
if addrfamily in [ARPHDR_ETHER, ARPHDR_LOOPBACK, ARPHDR_PPP, ARPHDR_TUN]:
return str2mac(mac)
else:
raise Scapy_Exception("Unsupported address family (%i) for interface [%s]" % (addrfamily, iff)) # noqa: E501
return resolve_iface(iff).mac or "00:00:00:00:00:00"


def get_if_addr6(niff):
Expand Down Expand Up @@ -128,9 +122,7 @@ def get_if_raw_addr6(iff):

# Next step is to import following architecture specific functions:
# def attach_filter(s, filter, iface)
# def get_if(iff,cmd)
# def get_if_raw_addr(iff)
# def get_if_raw_hwaddr(iff)
# def in6_getifaddr()
# def read_nameservers()
# def read_routes()
Expand Down Expand Up @@ -162,9 +154,6 @@ def get_if_raw_addr6(iff):
def get_if_raw_addr(iff: Union['NetworkInterface', str]) -> bytes:
return b"\0\0\0\0"

def get_if_raw_hwaddr(iff: Union['NetworkInterface', str]) -> Tuple[int, bytes]:
return -1, b""

def in6_getifaddr() -> List[Tuple[str, int, str]]:
return []

Expand Down
15 changes: 0 additions & 15 deletions scapy/arch/bpf/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,11 @@
from scapy.arch.common import compile_filter
from scapy.config import conf
from scapy.consts import LINUX
from scapy.data import ARPHDR_LOOPBACK, ARPHDR_ETHER
from scapy.error import Scapy_Exception
from scapy.utils import mac2str
from scapy.interfaces import (
InterfaceProvider,
NetworkInterface,
_GlobInterfaceType,
resolve_iface,
)

# re-export
Expand All @@ -40,7 +37,6 @@
Dict,
List,
Tuple,
Union,
)

if LINUX:
Expand Down Expand Up @@ -82,17 +78,6 @@ def attach_filter(fd, bpf_filter, iface):
raise Scapy_Exception("Can't attach the BPF filter !")


def get_if_raw_hwaddr(iface):
# type: (Union[NetworkInterface, str]) -> Tuple[int, bytes]
_iface = resolve_iface(iface)
if _iface == conf.loopback_name:
return ARPHDR_LOOPBACK, b"\x00" * 6
return (
ARPHDR_ETHER,
_iface.mac and mac2str(_iface.mac) or b"\x00" * 6,
)


def in6_getifaddr():
# type: () -> List[Tuple[str, int, str]]
"""
Expand Down
3 changes: 1 addition & 2 deletions scapy/arch/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,8 @@ def compile_filter(filter_exp, # type: str
)
iface = conf.iface
# Try to guess linktype to avoid requiring root
from scapy.arch import get_if_raw_hwaddr
try:
arphd = get_if_raw_hwaddr(iface)[0]
arphd = resolve_iface(iface).type
linktype = ARPHRD_TO_DLT.get(arphd)
except Exception:
# Failed to use linktype: use the interface
Expand Down
57 changes: 35 additions & 22 deletions scapy/arch/libpcap.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from scapy.automaton import select_objects
from scapy.compat import raw, plain_str
from scapy.config import conf
from scapy.consts import WINDOWS
from scapy.consts import WINDOWS, LINUX, BSD, SOLARIS
from scapy.data import (
DLT_RAW_ALT,
DLT_RAW,
Expand Down Expand Up @@ -217,6 +217,7 @@ def load_winpcapy():
flags = p.contents.flags # FLAGS
ips = []
mac = ""
itype = -1
a = p.contents.addresses
while a:
# IPv4 address
Expand Down Expand Up @@ -244,7 +245,7 @@ def load_winpcapy():
ips.append(addr)
a = a.contents.next
flags = FlagValue(flags, _pcap_if_flags)
if_list[name] = (description, ips, flags, mac)
if_list[name] = (description, ips, flags, mac, itype)
p = p.contents.next
conf.cache_pcapiflist = if_list
except Exception:
Expand Down Expand Up @@ -297,15 +298,13 @@ def __init__(self,
network_name(device).encode("utf8")
)
self.dtl = -1
if monitor:
if not WINDOWS or conf.use_npcap:
from scapy.libs.winpcapy import pcap_create
self.pcap = pcap_create(self.iface, self.errbuf)
if not self.pcap:
error = decode_locale_str(bytearray(self.errbuf).strip(b"\x00"))
if error:
raise OSError(error)
if WINDOWS and not conf.use_npcap:
raise OSError("On Windows, this feature requires NPcap !")
# Non-winpcap functions
from scapy.libs.winpcapy import (
pcap_set_snaplen,
Expand All @@ -316,11 +315,27 @@ def __init__(self,
pcap_statustostr,
pcap_geterr,
)
pcap_set_snaplen(self.pcap, snaplen)
pcap_set_promisc(self.pcap, promisc)
pcap_set_timeout(self.pcap, to_ms)
if pcap_set_rfmon(self.pcap, 1) != 0:
log_runtime.error("Could not set monitor mode")
if pcap_set_snaplen(self.pcap, snaplen) != 0:
error = decode_locale_str(bytearray(self.errbuf).strip(b"\x00"))
if error:
raise OSError(error)
log_runtime.error("Could not set snaplen")
if pcap_set_promisc(self.pcap, promisc) != 0:
error = decode_locale_str(bytearray(self.errbuf).strip(b"\x00"))
if error:
raise OSError(error)
log_runtime.error("Could not set promisc")
if pcap_set_timeout(self.pcap, to_ms) != 0:
error = decode_locale_str(bytearray(self.errbuf).strip(b"\x00"))
if error:
raise OSError(error)
log_runtime.error("Could not set timeout")
if monitor:
if pcap_set_rfmon(self.pcap, 1) != 0:
error = decode_locale_str(bytearray(self.errbuf).strip(b"\x00"))
if error:
raise OSError(error)
log_runtime.error("Could not set monitor mode")
status = pcap_activate(self.pcap)
# status == 0 means success
# status < 0 means error
Expand Down Expand Up @@ -350,6 +365,8 @@ def __init__(self,
errmsg = "%s: %s" % (iface, statusstr)
raise OSError(errmsg)
else:
if WINDOWS and monitor:
raise OSError("On Windows, this feature requires NPcap !")
self.pcap = pcap_open_live(self.iface,
snaplen, promisc, to_ms,
self.errbuf)
Expand Down Expand Up @@ -445,27 +462,23 @@ def load(self):
data = {}
i = 0
for ifname, dat in conf.cache_pcapiflist.items():
description, ips, flags, mac = dat
description, ips, flags, mac, itype = dat
i += 1
if not mac:
from scapy.arch import get_if_hwaddr
if LINUX or BSD or SOLARIS and not mac:
from scapy.arch.unix import get_if_raw_hwaddr
try:
mac = get_if_hwaddr(ifname)
except Exception as ex:
itype, _mac = get_if_raw_hwaddr(ifname)
mac = str2mac(_mac)
except Exception:
# There are at least 3 different possible exceptions
log_loading.warning(
"Could not get MAC address of interface '%s': %s." % (
ifname,
ex,
)
)
continue
mac = "00:00:00:00:00:00"
if_data = {
'name': ifname,
'description': description or ifname,
'network_name': ifname,
'index': i,
'mac': mac,
'type': itype,
'ips': ips,
'flags': flags
}
Expand Down
5 changes: 1 addition & 4 deletions scapy/arch/linux/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@

from scapy.compat import raw
from scapy.consts import LINUX
from scapy.arch.common import (
compile_filter,
)
from scapy.arch.common import compile_filter
from scapy.config import conf
from scapy.data import MTU, ETH_P_ALL, SOL_PACKET, SO_ATTACH_FILTER, \
SO_TIMESTAMPNS
Expand All @@ -46,7 +44,6 @@

# re-export
from scapy.arch.common import get_if_raw_addr, read_nameservers # noqa: F401
from scapy.arch.unix import get_if_raw_hwaddr # noqa: F401
from scapy.arch.linux.rtnetlink import ( # noqa: F401
read_routes,
read_routes6,
Expand Down
2 changes: 2 additions & 0 deletions scapy/arch/linux/rtnetlink.py
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,7 @@ def _get_if_list():
ifindex = msg.ifi_index
ifname = None
mac = "00:00:00:00:00:00"
itype = msg.ifi_type
ifflags = msg.ifi_flags
ips = []
for attr in msg.data:
Expand All @@ -826,6 +827,7 @@ def _get_if_list():
"index": ifindex,
"flags": ifflags,
"mac": mac,
"type": itype,
"ips": ips,
}
return interfaces
Expand Down
6 changes: 2 additions & 4 deletions scapy/arch/unix.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from scapy.config import conf
from scapy.consts import FREEBSD, NETBSD, OPENBSD, SOLARIS
from scapy.error import log_runtime, warning
from scapy.interfaces import network_name, NetworkInterface
from scapy.pton_ntop import inet_pton
from scapy.utils6 import in6_getscope, construct_source_candidate_set
from scapy.utils6 import in6_isvalid, in6_ismlladdr, in6_ismnladdr
Expand All @@ -33,18 +32,17 @@


def get_if(iff, cmd):
# type: (Union[NetworkInterface, str], int) -> bytes
# type: (str, int) -> bytes
"""Ease SIOCGIF* ioctl calls"""

iff = network_name(iff)
sck = socket.socket()
try:
return ioctl(sck, cmd, struct.pack("16s16x", iff.encode("utf8")))
finally:
sck.close()


def get_if_raw_hwaddr(iff, # type: Union[NetworkInterface, str]
def get_if_raw_hwaddr(iff, # type: str
siocgifhwaddr=None, # type: Optional[int]
):
# type: (...) -> Tuple[int, bytes]
Expand Down
12 changes: 3 additions & 9 deletions scapy/arch/windows/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@
from scapy.interfaces import NetworkInterface, InterfaceProvider, \
dev_from_index, resolve_iface, network_name
from scapy.pton_ntop import inet_ntop
from scapy.utils import atol, itom, mac2str, str2mac
from scapy.utils import atol, itom, str2mac
from scapy.utils6 import construct_source_candidate_set, in6_getscope
from scapy.data import ARPHDR_ETHER
from scapy.compat import plain_str
from scapy.supersocket import SuperSocket

Expand Down Expand Up @@ -297,6 +296,7 @@ def _get_ips(x):
"description": plain_str(x["description"]),
"guid": plain_str(x["adapter_name"]),
"mac": _get_mac(x),
"type": x["interface_type"],
"ipv4_metric": 0 if WINDOWS_XP else x["ipv4_metric"],
"ipv6_metric": 0 if WINDOWS_XP else x["ipv6_metric"],
"ips": _get_ips(x),
Expand Down Expand Up @@ -626,7 +626,7 @@ def iterinterfaces() -> Iterator[
# We have a libpcap provider: enrich pcap interfaces with
# Windows data
for netw, if_data in conf.cache_pcapiflist.items():
name, ips, flags, _ = if_data
name, ips, flags, _, _ = if_data
guid = _pcapname_to_guid(netw)
if guid == legacy_npcap_guid:
# Legacy Npcap detected !
Expand Down Expand Up @@ -785,12 +785,6 @@ def open_pcap(device, # type: Union[str, NetworkInterface]
libpcap.open_pcap = open_pcap # type: ignore


def get_if_raw_hwaddr(iface):
# type: (Union[NetworkInterface, str]) -> Tuple[int, bytes]
_iface = resolve_iface(iface)
return ARPHDR_ETHER, _iface.mac and mac2str(_iface.mac) or b"\x00" * 6


def _read_routes_c_v1():
# type: () -> List[Tuple[int, int, str, str, str, int]]
"""Retrieve Windows routes through a GetIpForwardTable call.
Expand Down
2 changes: 1 addition & 1 deletion scapy/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ class Conf(ConfClass):
#: holds the Scapy interface list and manager
ifaces = None # type: 'scapy.interfaces.NetworkInterfaceDict'
#: holds the cache of interfaces loaded from Libpcap
cache_pcapiflist = {} # type: Dict[str, Tuple[str, List[str], Any, str]]
cache_pcapiflist = {} # type: Dict[str, Tuple[str, List[str], Any, str, int]]
# `neighbor` will be filed by scapy.layers.l2
neighbor = None # type: 'scapy.layers.l2.Neighbor'
#: holds the name servers IP/hosts used for custom DNS resolution
Expand Down
25 changes: 14 additions & 11 deletions scapy/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ def __init__(self,
self.index = -1
self.ip = None # type: Optional[str]
self.ips = defaultdict(list) # type: DefaultDict[int, List[str]]
self.type = -1
self.mac = None # type: Optional[str]
self.dummy = False
if data is not None:
Expand All @@ -132,6 +133,7 @@ def update(self, data):
self.network_name = data.get('network_name', "")
self.index = data.get('index', 0)
self.ip = data.get('ip', "")
self.type = data.get('type', -1)
self.mac = data.get('mac', "")
self.flags = data.get('flags', 0)
self.dummy = data.get('dummy', False)
Expand Down Expand Up @@ -416,19 +418,20 @@ def resolve_iface(dev):
return conf.ifaces.dev_from_name(dev)
except ValueError:
try:
return dev_from_networkname(dev)
return conf.ifaces.dev_from_networkname(dev)
except ValueError:
pass
# Return a dummy interface
return NetworkInterface(
InterfaceProvider(),
data={
"name": dev,
"description": dev,
"network_name": dev,
"dummy": True
}
)
# Nothing found yet. Reload to detect if it was added recently
conf.ifaces.reload()
try:
return conf.ifaces.dev_from_name(dev)
except ValueError:
try:
return conf.ifaces.dev_from_networkname(dev)
except ValueError:
pass
# Not found
raise OSError("Interface '%s' not found !" % dev)


def network_name(dev):
Expand Down
Loading

0 comments on commit 429dbf1

Please sign in to comment.