• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# SPDX-License-Identifier: GPL-2.0-only
2# This file is part of Scapy
3# See https://scapy.net/ for more information
4# Copyright (C) Philippe Biondi <phil@secdev.org>
5
6"""
7Operating system specific functionality.
8"""
9
10import socket
11import sys
12
13from scapy.compat import orb
14from scapy.config import conf, _set_conf_sockets
15from scapy.consts import LINUX, SOLARIS, WINDOWS, BSD
16from scapy.data import (
17    IPV6_ADDR_GLOBAL,
18    IPV6_ADDR_LOOPBACK,
19)
20from scapy.error import log_loading
21from scapy.interfaces import (
22    _GlobInterfaceType,
23    network_name,
24    resolve_iface,
25)
26from scapy.pton_ntop import inet_pton, inet_ntop
27
28from scapy.libs.extcap import load_extcap
29
30# Typing imports
31from typing import (
32    List,
33    Optional,
34    Tuple,
35    Union,
36    TYPE_CHECKING,
37)
38
39if TYPE_CHECKING:
40    from scapy.interfaces import NetworkInterface
41
42# Note: the typing of this file is heavily ignored because MyPy doesn't allow
43# to import the same function from different files.
44
45# This list only includes imports that are common across all platforms.
46__all__ = [  # noqa: F405
47    "get_if_addr",
48    "get_if_addr6",
49    "get_if_hwaddr",
50    "get_if_list",
51    "get_if_raw_addr",
52    "get_if_raw_addr6",
53    "get_working_if",
54    "in6_getifaddr",
55    "read_nameservers",
56    "read_routes",
57    "read_routes6",
58    "load_extcap",
59    "SIOCGIFHWADDR",
60]
61
62# BACKWARD COMPATIBILITY
63from scapy.interfaces import (
64    get_if_list,
65    get_working_if,
66)
67
68
69# We build the utils functions BEFORE importing the underlying handlers
70# because they might be themselves imported within the arch/ folder.
71
72def str2mac(s):
73    # Duplicated from scapy/utils.py for import reasons
74    # type: (bytes) -> str
75    return ("%02x:" * 6)[:-1] % tuple(orb(x) for x in s)
76
77
78def get_if_addr(iff):
79    # type: (_GlobInterfaceType) -> str
80    """
81    Returns the IPv4 of an interface or "0.0.0.0" if not available
82    """
83    return inet_ntop(socket.AF_INET, get_if_raw_addr(iff))  # noqa: F405
84
85
86def get_if_hwaddr(iff):
87    # type: (_GlobInterfaceType) -> str
88    """
89    Returns the MAC (hardware) address of an interface
90    """
91    return resolve_iface(iff).mac or "00:00:00:00:00:00"
92
93
94def get_if_addr6(niff):
95    # type: (_GlobInterfaceType) -> Optional[str]
96    """
97    Returns the main global unicast address associated with provided
98    interface, in human readable form. If no global address is found,
99    None is returned.
100    """
101    iff = network_name(niff)
102    scope = IPV6_ADDR_GLOBAL
103    if iff == conf.loopback_name:
104        scope = IPV6_ADDR_LOOPBACK
105    return next((x[0] for x in in6_getifaddr()
106                 if x[2] == iff and x[1] == scope), None)
107
108
109def get_if_raw_addr6(iff):
110    # type: (_GlobInterfaceType) -> Optional[bytes]
111    """
112    Returns the main global unicast address associated with provided
113    interface, in network format. If no global address is found, None
114    is returned.
115    """
116    ip6 = get_if_addr6(iff)
117    if ip6 is not None:
118        return inet_pton(socket.AF_INET6, ip6)
119
120    return None
121
122
123# Next step is to import following architecture specific functions:
124# def attach_filter(s, filter, iface)
125# def get_if_raw_addr(iff)
126# def in6_getifaddr()
127# def read_nameservers()
128# def read_routes()
129# def read_routes6()
130# def set_promisc(s,iff,val=1)
131
132if LINUX:
133    from scapy.arch.linux import *  # noqa F403
134elif BSD:
135    from scapy.arch.bpf.core import *  # noqa F403
136    if not conf.use_pcap:
137        # Native
138        from scapy.arch.bpf.supersocket import *  # noqa F403
139        conf.use_bpf = True
140    SIOCGIFHWADDR = 0  # mypy compat
141elif SOLARIS:
142    from scapy.arch.solaris import *  # noqa F403
143elif WINDOWS:
144    from scapy.arch.windows import *  # noqa F403
145    from scapy.arch.windows.native import *  # noqa F403
146    SIOCGIFHWADDR = 0  # mypy compat
147else:
148    log_loading.critical(
149        "Scapy currently does not support %s! I/O will NOT work!" % sys.platform
150    )
151    SIOCGIFHWADDR = 0  # mypy compat
152
153    # DUMMYS
154    def get_if_raw_addr(iff: Union['NetworkInterface', str]) -> bytes:
155        return b"\0\0\0\0"
156
157    def in6_getifaddr() -> List[Tuple[str, int, str]]:
158        return []
159
160    def read_nameservers() -> List[str]:
161        return []
162
163    def read_routes() -> List[str]:
164        return []
165
166    def read_routes6() -> List[str]:
167        return []
168
169if LINUX or BSD:
170    conf.load_layers.append("tuntap")
171
172_set_conf_sockets()  # Apply config
173