Source code for switchyard.lib.interface

from ipaddress import ip_interface, IPv6Interface, IPv4Interface, IPv6Address, IPv4Address
from enum import Enum
from socket import if_nametoindex

from .address import IPAddr,EthAddr
from .logging import log_debug
from ..pcapffi import pcap_devices

[docs]class InterfaceType(Enum): Unknown=1 Loopback=2 Wired=3 Wireless=4
[docs]class Interface(object): __slots__ = ['__name','__ethaddr','__ipaddr','__ifnum','__iftype'] __nextnum = 1 ''' Class that models a single logical interface on a network device. An interface has a name, 48-bit Ethernet MAC address, and (optionally) an IP address and network mask. An interface also has a number associated with it and a type, which is one of the values of the enumerated type ``InterfaceType``. ''' def __init__(self, name, ethaddr, ipaddr=None, netmask=None, ifnum=None, iftype=InterfaceType.Unknown): self.__name = name self.ethaddr = ethaddr if netmask: ipaddr = "{}/{}".format(ipaddr,netmask) self.ipaddr = ipaddr self.ifnum = ifnum self.__iftype = iftype @property def name(self): '''Get the name of the interface''' return self.__name @property def ethaddr(self): '''Get the Ethernet address associated with the interface''' return self.__ethaddr @ethaddr.setter def ethaddr(self, value): if isinstance(value, EthAddr): self.__ethaddr = value elif isinstance(value, (str,bytes)): self.__ethaddr = EthAddr(value) elif value is None: self.__ethaddr = EthAddr('00:00:00:00:00:00') else: raise ValueError("Can't initialize ethaddr with {}".format(value)) @property def ipaddr(self): '''Get the IPv4 address associated with the interface''' return self.__ipaddr.ip @property def ipinterface(self): ''' Returns the address assigned to this interface as an IPInterface object. (see documentation for the built-in ipaddress module). ''' return self.__ipaddr @ipaddr.setter def ipaddr(self, value): if isinstance(value, (str,IPAddr)): self.__ipaddr = ip_interface(value) elif value is None: self.__ipaddr = ip_interface('0.0.0.0') else: raise Exception("Invalid type assignment to IP address (must be string or existing IP address)") @property def netmask(self): '''Get the IPv4 subnet mask associated with the interface''' return self.__ipaddr.netmask @netmask.setter def netmask(self, value): if isinstance(value, (IPAddr,str,int)): self.__ipaddr = ip_interface("{}/{}".format(self.__ipaddr.ip, str(value))) elif value is None: self.__ipaddr = ip_interface("{}/32".format(self.__ipaddr.ip)) else: raise Exception("Invalid type assignment to netmask (must be IPAddr, string, or int)") @property def ifnum(self): '''Get the interface number (integer) associated with the interface''' return self.__ifnum @ifnum.setter def ifnum(self, value): if not isinstance(value, int): value = Interface.__nextnum Interface.__nextnum += 1 self.__ifnum = int(value) @property def iftype(self): '''Get the type of the interface as a value from the InterfaceType enumeration.''' return self.__iftype def __str__(self): s = "{} mac:{}".format(str(self.name), str(self.ethaddr)) if int(self.ipaddr) != 0: s += " ip:{}".format(self.__ipaddr) return s
def make_device_list(includes=set(), excludes=set()): log_debug("Making device list. Includes: {}, Excludes: {}".format(includes, excludes)) non_interfaces = set() devs = set([ dev.name for dev in pcap_devices() if not dev.isloop or dev.name in includes]) includes = set(includes) # may have been given as a list includes.intersection_update(devs) # only include devs that actually exist for d in devs: try: ifnum = if_nametoindex(d) except: non_interfaces.add(d) devs.difference_update(non_interfaces) log_debug("Devices found: {}".format(devs)) # remove devs from excludelist devs.difference_update(set(excludes)) # if includelist is non-empty, perform # intersection with devs found and includelist if includes: devs.intersection_update(includes) log_debug("Using these devices: {}".format(devs)) return devs