Example #1
0
class Router(EntityWithNIC):

    def __init__(self, n_interfaces=3):
        super(Router, self).__init__(n_interfaces)
        self.interfaces = [Interface(self, nic) for nic in self.nics]
        each(self.interfaces).report.connect(self.report)
        each(self.interfaces).on_ipv4.connect(self.on_ipv4)
        self.routes = RouteTable()

    def on_ipv4(self, frame, **kwargs):
        i_interface = kwargs.get('interface')
        packet = Packet(frame.payload)
        try:
            net, _, gateway, interface = self.routes.find(packet.dst_ip)
        except KeyError:
            self.report('do not know how to route packet for {}',
                        packet.dst_ip)
        else:
            if interface != i_interface:
                interface.send_packet(
                    data=packet.raw,
                    dst_ip=gateway if gateway else packet.dst_ip,
                    ethertype=frame.ethertype,
                )
            else:
                self.report('packet dst to {} already on net {}, ignored',
                            packet.dst_ip, net)

    def __getitem__(self, index):
        return self.interfaces[index]

    def run(self):
        while True:
            each(self.interfaces).do_send()
            each(self.interfaces).do_recv()
            mint.elapse(1)

    @property
    def status(self):
        return [
            ('routes', lambda: self.routes),
        ] + [
            ('if{}'.format(i), interface)
            for i, interface in enumerate(self.interfaces)
        ]
Example #2
0
class Router(EntityWithNIC):
    def __init__(self, n_interfaces=3):
        super(Router, self).__init__(n_interfaces)
        self.interfaces = [Interface(self, nic) for nic in self.nics]
        each(self.interfaces).report.connect(self.report)
        each(self.interfaces).on_ipv4.connect(self.on_ipv4)
        self.routes = RouteTable()

    def on_ipv4(self, frame, **kwargs):
        i_interface = kwargs.get('interface')
        packet = Packet(frame.payload)
        try:
            net, _, gateway, interface = self.routes.find(packet.dst_ip)
        except KeyError:
            self.report('do not know how to route packet for {}',
                        packet.dst_ip)
        else:
            if interface != i_interface:
                interface.send_packet(
                    data=packet.raw,
                    dst_ip=gateway if gateway else packet.dst_ip,
                    ethertype=frame.ethertype,
                )
            else:
                self.report('packet dst to {} already on net {}, ignored',
                            packet.dst_ip, net)

    def __getitem__(self, index):
        return self.interfaces[index]

    def run(self):
        while True:
            each(self.interfaces).do_send()
            each(self.interfaces).do_recv()
            mint.elapse(1)

    @property
    def status(self):
        return [
            ('routes', lambda: self.routes),
        ] + [('if{}'.format(i), interface)
             for i, interface in enumerate(self.interfaces)]
Example #3
0
class Host(EntityWithNIC):

    def __init__(self, **kwargs):
        super(Host, self).__init__(n_interfaces=1)
        self.libsocket = LibSocket(self)
        self.sockets = {
            Packet.Protocol.TCP: {},
            Packet.Protocol.UDP: {},
        }
        self.ports = {
            LibSocket.SOCK_DGRAM: deque(range(49152, 65535)),
            LibSocket.SOCK_STREAM: deque(range(49152, 65535)),
        }

        ip = kwargs.get('ip', None)
        mac = kwargs.get('mac', None)

        self.interfaces = [Interface(self, nic, ip, mac) for nic in self.nics]
        self.interface = self.interfaces[0]
        self.interface.on_ipv4.connect(self.on_ipv4)
        self.interface.report.connect(self.report)

        self.routes = RouteTable(self)

        self.dhcp_client = DHCPClient(self)

    def send_udp(self, data, src_port, dst_ip, dst_port):
        src_port = Port(src_port)
        dst_port = Port(dst_port)
        datagram = Datagram(
            src_port=src_port,
            dst_port=dst_port,
            payload=data,
        )
        self.send_ip(datagram.raw, dst_ip, protocol=Packet.Protocol.UDP)

    def send_ip(self, data, dst_ip, protocol=Packet.Protocol.Raw):
        dst_ip = IP(dst_ip)
        if not dst_ip:
            self.report('invalid dst_ip {}, ignored', dst_ip)
            return
        try:
            _, _, gateway, interface = self.routes.find(dst_ip)
        except KeyError:
            self.report('no gateway for destination {}, ignored', dst_ip)
            return

        if gateway:
            self.report('{} is non-local, beg {} to deliver', dst_ip, gateway)
        else:
            self.report('{} is local, send directly', dst_ip)

        packet = Packet(
            src_ip=interface.ip,
            dst_ip=dst_ip,
            protocol=protocol,
            payload=data,
        )
        interface.send_packet(
            packet.raw,
            gateway if gateway else dst_ip,
            Frame.EtherType.IPv4,
        )

    @property
    def ip(self):
        return self.interface.ip

    @ip.setter
    def ip(self, val):
        self.interface.ip = val
        self.report('ip changed to {}', self.interface.ip)

    @property
    def mask(self):
        return self.interface.mask

    @mask.setter
    def mask(self, val):
        self.interface.mask = val
        self.report('subnet mask changed to {}', self.interface.mask)

    @property
    def mac(self):
        return self.interface.mac

    @mac.setter
    def mac(self, val):
        self.interface.mac = val

    @property
    def default_gateway(self):
        return self._default_gateway

    @default_gateway.setter
    def default_gateway(self, val):
        gateway = IP(val)
        self._default_gateway = gateway
        self.routes[-1].gateway = gateway
        self.report('default gateway changed to {}', gateway)

    def on_ipv4(self, frame, **_):
        packet = Packet(frame.payload)
        if packet.protocol == Packet.Protocol.TCP:
            PDU = Segment
        elif packet.protocol == Packet.Protocol.UDP:
            PDU = Datagram
        else:
            self.report('unsupported transport layer protocol')
            return
        self.on_transport_pdu(packet, PDU)

    def on_transport_pdu(self, packet, PDU):
        pdu = PDU(packet.payload)
        try:
            addr2socket = self.sockets[packet.protocol]
        except KeyError:
            pass
        else:
            ip, port = packet.dst_ip, pdu.dst_port
            if ip == IP_Broadcast:
                ip = self.ip
            try:
                sock = addr2socket[(ip, port)]
            except KeyError:
                self.report(
                    'no handler at {} {}:{}, ignored',
                    Packet.Protocol[packet.protocol],
                    packet.dst_ip, pdu.dst_port,
                )
            else:
                sock.feed(pdu, packet.src_ip)

    def run(self):
        if not self.ip:
            self.dhcp = DHCPClient(self)
        while True:
            self.interface.do_send()
            self.interface.do_recv()
            mint.elapse(1)

    def bind(self, sock, addr):
        ip, port = addr

        ip = IP(ip)
        if not ip:
            ip = self.interface.ip

        if port is None:
            port = self.ports[sock.type].popleft()
        port = Port(port)

        addr = (ip, port)

        addr2socket = self.get_addr2socket(sock)
        addr2socket[addr] = sock
        return addr

    def close_socket(self, sock):
        addr2socket = self.get_addr2socket(sock)
        sock = addr2socket.pop(sock.addr, None)
        if sock:
            self.ports[sock.type].append(sock.port)

    def get_addr2socket(self, sock):
        if sock.type == LibSocket.SOCK_DGRAM:
            addr2socket = self.sockets[Packet.Protocol.UDP]
        elif sock.type == LibSocket.SOCK_STREAM:
            addr2socket = self.sockets[Packet.Protocol.TCP]
        else:
            self.report('invalid bind')
            return (None, None)
        return addr2socket

    @property
    def status(self):
        nic_title = 'IP:{}/{} MAC:{}'.format(
            self.ip, self.mask.net_len, self.mac)
        return [
            (nic_title, self.interface),
            ('O', Discomposer(lambda: self.nic.odata)),
            ('I', Discomposer(lambda: self.nic.idata)),
        ]
Example #4
0
class Host(EntityWithNIC):

    def __init__(self, **kwargs):
        super(Host, self).__init__(n_interfaces=1)
        self.libsocket = LibSocket(self)

        ip = kwargs.get('ip', '192.168.0.1{:02}'.format(self.index))
        mask = kwargs.get('mask', '255.255.255.0')
        mac = kwargs.get('mac', None)

        self.interfaces = [Interface(self, nic, ip, mask, mac)
                           for nic in self.nics]
        self.interface = self.interfaces[0]
        self.interface.report.connect(self.report)
        self.interface.on_ipv4.connect(self.on_ipv4)

        self.routes = RouteTable(self)

    def send(self, data, ip, protocol=Packet.Protocol.Raw):
        dst_ip = IP(ip)
        _, _, gateway, interface = self.routes.find(dst_ip)

        if gateway:
            self.report('{} is non-local, beg {} to deliver', dst_ip, gateway)
        else:
            self.report('{} is local, send directly', dst_ip)

        packet = Packet(
            src_ip=interface.ip,
            dst_ip=dst_ip,
            protocol=protocol,
            payload=data,
        )
        interface.send_packet(
            packet.raw,
            gateway if gateway else dst_ip,
            Frame.EtherType.IPv4,
        )

    @property
    def ip(self):
        return self.interface.ip

    @ip.setter
    def ip(self, val):
        self.interface.ip = val

    @property
    def mask(self):
        return self.interface.mask

    @mask.setter
    def mask(self, val):
        self.interface.mask = val

    @property
    def mac(self):
        return self.interface.mac

    @mac.setter
    def mac(self, val):
        self.interface.mac = val

    @property
    def default_gateway(self):
        return self._default_gateway

    @default_gateway.setter
    def default_gateway(self, val):
        gateway = IP(val)
        self._default_gateway = gateway
        self.routes[-1].gateway = gateway

    def on_ipv4(self, frame, **_):
        packet = Packet(frame.payload)
        self.send('wooo..', packet.src_ip)

    def run(self):
        while True:
            self.interface.do_send()
            self.interface.do_recv()
            mint.elapse(1)

    @property
    def status(self):
        nic_title = 'IP:{}/{} MAC:{}'.format(
            self.ip, self.mask.net_len, self.mac)
        return [
            (nic_title, self.nic),
            ('O', Discomposer(lambda: self.nic.odata)),
            ('I', Discomposer(lambda: self.nic.idata)),
        ]
Example #5
0
class Host(EntityWithNIC):
    def __init__(self, **kwargs):
        super(Host, self).__init__(n_interfaces=1)
        self.libsocket = LibSocket(self)

        ip = kwargs.get('ip', '192.168.0.1{:02}'.format(self.index))
        mask = kwargs.get('mask', '255.255.255.0')
        mac = kwargs.get('mac', None)

        self.interfaces = [
            Interface(self, nic, ip, mask, mac) for nic in self.nics
        ]
        self.interface = self.interfaces[0]
        self.interface.report.connect(self.report)
        self.interface.on_ipv4.connect(self.on_ipv4)

        self.routes = RouteTable(self)

    def send(self, data, ip, protocol=Packet.Protocol.Raw):
        dst_ip = IP(ip)
        _, _, gateway, interface = self.routes.find(dst_ip)

        if gateway:
            self.report('{} is non-local, beg {} to deliver', dst_ip, gateway)
        else:
            self.report('{} is local, send directly', dst_ip)

        packet = Packet(
            src_ip=interface.ip,
            dst_ip=dst_ip,
            protocol=protocol,
            payload=data,
        )
        interface.send_packet(
            packet.raw,
            gateway if gateway else dst_ip,
            Frame.EtherType.IPv4,
        )

    @property
    def ip(self):
        return self.interface.ip

    @ip.setter
    def ip(self, val):
        self.interface.ip = val

    @property
    def mask(self):
        return self.interface.mask

    @mask.setter
    def mask(self, val):
        self.interface.mask = val

    @property
    def mac(self):
        return self.interface.mac

    @mac.setter
    def mac(self, val):
        self.interface.mac = val

    @property
    def default_gateway(self):
        return self._default_gateway

    @default_gateway.setter
    def default_gateway(self, val):
        gateway = IP(val)
        self._default_gateway = gateway
        self.routes[-1].gateway = gateway

    def on_ipv4(self, frame, **_):
        packet = Packet(frame.payload)
        self.send('wooo..', packet.src_ip)

    def run(self):
        while True:
            self.interface.do_send()
            self.interface.do_recv()
            mint.elapse(1)

    @property
    def status(self):
        nic_title = 'IP:{}/{} MAC:{}'.format(self.ip, self.mask.net_len,
                                             self.mac)
        return [
            (nic_title, self.nic),
            ('O', Discomposer(lambda: self.nic.odata)),
            ('I', Discomposer(lambda: self.nic.idata)),
        ]
Example #6
0
class Host(EntityWithNIC):
    def __init__(self, **kwargs):
        super(Host, self).__init__(n_interfaces=1)
        self.libsocket = LibSocket(self)
        self.sockets = {
            Packet.Protocol.TCP: {},
            Packet.Protocol.UDP: {},
        }
        self.ports = {
            LibSocket.SOCK_DGRAM: deque(range(49152, 65535)),
            LibSocket.SOCK_STREAM: deque(range(49152, 65535)),
        }

        ip = kwargs.get('ip', None)
        mac = kwargs.get('mac', None)

        self.interfaces = [Interface(self, nic, ip, mac) for nic in self.nics]
        self.interface = self.interfaces[0]
        self.interface.on_ipv4.connect(self.on_ipv4)
        self.interface.report.connect(self.report)

        self.routes = RouteTable(self)

        self.dhcp_client = DHCPClient(self)

    def send_udp(self, data, src_port, dst_ip, dst_port):
        src_port = Port(src_port)
        dst_port = Port(dst_port)
        datagram = Datagram(
            src_port=src_port,
            dst_port=dst_port,
            payload=data,
        )
        self.send_ip(datagram.raw, dst_ip, protocol=Packet.Protocol.UDP)

    def send_ip(self, data, dst_ip, protocol=Packet.Protocol.Raw):
        dst_ip = IP(dst_ip)
        if not dst_ip:
            self.report('invalid dst_ip {}, ignored', dst_ip)
            return
        try:
            _, _, gateway, interface = self.routes.find(dst_ip)
        except KeyError:
            self.report('no gateway for destination {}, ignored', dst_ip)
            return

        if gateway:
            self.report('{} is non-local, beg {} to deliver', dst_ip, gateway)
        else:
            self.report('{} is local, send directly', dst_ip)

        packet = Packet(
            src_ip=interface.ip,
            dst_ip=dst_ip,
            protocol=protocol,
            payload=data,
        )
        interface.send_packet(
            packet.raw,
            gateway if gateway else dst_ip,
            Frame.EtherType.IPv4,
        )

    @property
    def ip(self):
        return self.interface.ip

    @ip.setter
    def ip(self, val):
        self.interface.ip = val
        self.report('ip changed to {}', self.interface.ip)

    @property
    def mask(self):
        return self.interface.mask

    @mask.setter
    def mask(self, val):
        self.interface.mask = val
        self.report('subnet mask changed to {}', self.interface.mask)

    @property
    def mac(self):
        return self.interface.mac

    @mac.setter
    def mac(self, val):
        self.interface.mac = val

    @property
    def default_gateway(self):
        return self._default_gateway

    @default_gateway.setter
    def default_gateway(self, val):
        gateway = IP(val)
        self._default_gateway = gateway
        self.routes[-1].gateway = gateway
        self.report('default gateway changed to {}', gateway)

    def on_ipv4(self, frame, **_):
        packet = Packet(frame.payload)
        if packet.protocol == Packet.Protocol.TCP:
            PDU = Segment
        elif packet.protocol == Packet.Protocol.UDP:
            PDU = Datagram
        else:
            self.report('unsupported transport layer protocol')
            return
        self.on_transport_pdu(packet, PDU)

    def on_transport_pdu(self, packet, PDU):
        pdu = PDU(packet.payload)
        try:
            addr2socket = self.sockets[packet.protocol]
        except KeyError:
            pass
        else:
            ip, port = packet.dst_ip, pdu.dst_port
            if ip == IP_Broadcast:
                ip = self.ip
            try:
                sock = addr2socket[(ip, port)]
            except KeyError:
                self.report(
                    'no handler at {} {}:{}, ignored',
                    Packet.Protocol[packet.protocol],
                    packet.dst_ip,
                    pdu.dst_port,
                )
            else:
                sock.feed(pdu, packet.src_ip)

    def run(self):
        if not self.ip:
            self.dhcp = DHCPClient(self)
        while True:
            self.interface.do_send()
            self.interface.do_recv()
            mint.elapse(1)

    def bind(self, sock, addr):
        ip, port = addr

        ip = IP(ip)
        if not ip:
            ip = self.interface.ip

        if port is None:
            port = self.ports[sock.type].popleft()
        port = Port(port)

        addr = (ip, port)

        addr2socket = self.get_addr2socket(sock)
        addr2socket[addr] = sock
        return addr

    def close_socket(self, sock):
        addr2socket = self.get_addr2socket(sock)
        sock = addr2socket.pop(sock.addr, None)
        if sock:
            self.ports[sock.type].append(sock.port)

    def get_addr2socket(self, sock):
        if sock.type == LibSocket.SOCK_DGRAM:
            addr2socket = self.sockets[Packet.Protocol.UDP]
        elif sock.type == LibSocket.SOCK_STREAM:
            addr2socket = self.sockets[Packet.Protocol.TCP]
        else:
            self.report('invalid bind')
            return (None, None)
        return addr2socket

    @property
    def status(self):
        nic_title = 'IP:{}/{} MAC:{}'.format(self.ip, self.mask.net_len,
                                             self.mac)
        return [
            (nic_title, self.interface),
            ('O', Discomposer(lambda: self.nic.odata)),
            ('I', Discomposer(lambda: self.nic.idata)),
        ]