Ejemplo n.º 1
0
    def deladdr(self, addr: str) -> None:
        """
        Delete address from network interface.

        :param addr: address to delete
        :return: nothing
        :raises CoreCommandError: when there is a command exception
        """
        if self.up:
            self.net_client.delete_address(self.name, str(addr))
        CoreInterface.deladdr(self, addr)
Ejemplo n.º 2
0
    def deladdr(self, addr):
        """
        Delete address from network interface.

        :param str addr: address to delete
        :return: nothing
        :raises CoreCommandError: when there is a command exception
        """
        if self.up:
            utils.check_cmd(
                [constants.IP_BIN, "addr", "del",
                 str(addr), "dev", self.name])

        CoreInterface.deladdr(self, addr)
Ejemplo n.º 3
0
class Rj45Node(CoreNodeBase):
    """
    RJ45Node is a physical interface on the host linked to the emulated
    network.
    """

    apitype: NodeTypes = NodeTypes.RJ45
    type: str = "rj45"

    def __init__(
        self,
        session: "Session",
        _id: int = None,
        name: str = None,
        mtu: int = 1500,
        start: bool = True,
        server: DistributedServer = None,
    ) -> None:
        """
        Create an RJ45Node instance.

        :param session: core session instance
        :param _id: node id
        :param name: node name
        :param mtu: rj45 mtu
        :param start: start flag
        :param server: remote server node
            will run on, default is None for localhost
        """
        super().__init__(session, _id, name, start, server)
        self.interface = CoreInterface(session, self, name, name, mtu, server)
        self.interface.transport_type = TransportType.RAW
        self.lock: threading.RLock = threading.RLock()
        self.ifindex: Optional[int] = None
        self.old_up: bool = False
        self.old_addrs: List[Tuple[str, Optional[str]]] = []
        if start:
            self.startup()

    def startup(self) -> None:
        """
        Set the interface in the up state.

        :return: nothing
        :raises CoreCommandError: when there is a command exception
        """
        # interface will also be marked up during net.attach()
        self.savestate()
        self.net_client.device_up(self.interface.localname)
        self.up = True

    def shutdown(self) -> None:
        """
        Bring the interface down. Remove any addresses and queuing
        disciplines.

        :return: nothing
        """
        if not self.up:
            return
        localname = self.interface.localname
        self.net_client.device_down(localname)
        self.net_client.device_flush(localname)
        try:
            self.net_client.delete_tc(localname)
        except CoreCommandError:
            pass
        self.up = False
        self.restorestate()

    def newnetif(self, net: CoreNetworkBase, interface: InterfaceData) -> int:
        """
        This is called when linking with another node. Since this node
        represents an interface, we do not create another object here,
        but attach ourselves to the given network.

        :param net: new network instance
        :param interface: interface data for new interface
        :return: interface index
        :raises ValueError: when an interface has already been created, one max
        """
        with self.lock:
            ifindex = interface.id
            if ifindex is None:
                ifindex = 0
            if self.interface.net is not None:
                raise ValueError(
                    "RJ45 nodes support at most 1 network interface")
            self._netif[ifindex] = self.interface
            self.ifindex = ifindex
            if net is not None:
                self.interface.attachnet(net)
            for addr in interface.get_addresses():
                self.addaddr(addr)
            return ifindex

    def delnetif(self, ifindex: int) -> None:
        """
        Delete a network interface.

        :param ifindex: interface index to delete
        :return: nothing
        """
        if ifindex is None:
            ifindex = 0
        self._netif.pop(ifindex)
        if ifindex == self.ifindex:
            self.shutdown()
        else:
            raise ValueError(f"ifindex {ifindex} does not exist")

    def netif(self,
              ifindex: int,
              net: CoreNetworkBase = None) -> Optional[CoreInterface]:
        """
        This object is considered the network interface, so we only
        return self here. This keeps the RJ45Node compatible with
        real nodes.

        :param ifindex: interface index to retrieve
        :param net: network to retrieve
        :return: a network interface
        """
        if net is not None and net == self.interface.net:
            return self.interface
        if ifindex is None:
            ifindex = 0
        if ifindex == self.ifindex:
            return self.interface
        return None

    def getifindex(self, netif: CoreInterface) -> Optional[int]:
        """
        Retrieve network interface index.

        :param netif: network interface to retrieve
            index for
        :return: interface index, None otherwise
        """
        if netif != self.interface:
            return None
        return self.ifindex

    def addaddr(self, addr: str) -> None:
        """
        Add address to to network interface.

        :param addr: address to add
        :return: nothing
        :raises CoreCommandError: when there is a command exception
        """
        addr = utils.validate_ip(addr)
        if self.up:
            self.net_client.create_address(self.name, addr)
        self.interface.addaddr(addr)

    def deladdr(self, addr: str) -> None:
        """
        Delete address from network interface.

        :param addr: address to delete
        :return: nothing
        :raises CoreCommandError: when there is a command exception
        """
        if self.up:
            self.net_client.delete_address(self.name, addr)
        self.interface.deladdr(addr)

    def savestate(self) -> None:
        """
        Save the addresses and other interface state before using the
        interface for emulation purposes. TODO: save/restore the PROMISC flag

        :return: nothing
        :raises CoreCommandError: when there is a command exception
        """
        self.old_up = False
        self.old_addrs: List[Tuple[str, Optional[str]]] = []
        localname = self.interface.localname
        output = self.net_client.address_show(localname)
        for line in output.split("\n"):
            items = line.split()
            if len(items) < 2:
                continue
            if items[1] == f"{localname}:":
                flags = items[2][1:-1].split(",")
                if "UP" in flags:
                    self.old_up = True
            elif items[0] == "inet":
                self.old_addrs.append((items[1], items[3]))
            elif items[0] == "inet6":
                if items[1][:4] == "fe80":
                    continue
                self.old_addrs.append((items[1], None))
        logging.info("saved rj45 state: addrs(%s) up(%s)", self.old_addrs,
                     self.old_up)

    def restorestate(self) -> None:
        """
        Restore the addresses and other interface state after using it.

        :return: nothing
        :raises CoreCommandError: when there is a command exception
        """
        localname = self.interface.localname
        logging.info("restoring rj45 state: %s", localname)
        for addr in self.old_addrs:
            self.net_client.create_address(localname, addr[0], addr[1])
        if self.old_up:
            self.net_client.device_up(localname)

    def setposition(self,
                    x: float = None,
                    y: float = None,
                    z: float = None) -> None:
        """
        Uses setposition from both parent classes.

        :param x: x position
        :param y: y position
        :param z: z position
        :return: True if position changed, False otherwise
        """
        super().setposition(x, y, z)
        self.interface.setposition()

    def termcmdstring(self, sh: str) -> str:
        """
        Create a terminal command string.

        :param sh: shell to execute command in
        :return: str
        """
        raise NotImplementedError