Пример #1
0
Файл: VNS.py Проект: smbz/vns
    def handle_packet_from_outside(self, packet):
        """Forwards packet to the appropriate simulation, if any."""
        if len(packet) < 14:
            return # too small to even have an Ethernet header

        # determine which topology(ies) should receive this packet
        pkt = ProtocolHelper.Packet(packet)
        if pkt.is_valid_ipv4():
            topos = self.resolver.resolve_ip(pkt.ip_dst, pkt.ip_src)
            str_addr = 'dst=%s src=%s' % (addrstr(pkt.ip_dst), addrstr(pkt.ip_src))
            rewrite_dst_mac = True
        elif pkt.is_dst_mac_broadcast():
            return # ignore broadcasts
        else:
            topos = self.resolver.resolve_mac(pkt.mac_dst)
            str_addr = 'dst=%s' % addrstr(pkt.mac_dst)
            rewrite_dst_mac = False

        # forward the packet to the appropriate topology(ies)
        if topos:
            logging.debug('sniffed raw packet to %s (topology %s): %s' %
                          (str_addr, ','.join([str(t.id) for t in topos]), pktstr(packet)))
            for topo in topos:
                topo.create_job_for_incoming_packet(packet, rewrite_dst_mac)
                self.job_available_event.set()
Пример #2
0
    def register_topology(self, topo):
        """Registers a topology with the resolver."""
        if not topo.has_gateway():
            return # it is isolated from the real world

        for mac in topo.get_my_mac_addrs():
            try:
                self.m2t[mac].append(topo)
                logging.debug('%s: MAC registered: %s (shared)' % (topo, addrstr(mac)))
            except KeyError:
                self.m2t[mac] = [topo]
                logging.debug('%s: MAC registered: %s' % (topo, addrstr(mac)))

        for ip in topo.get_all_ip_addrs_in_my_ip_block():
            # get the source filtering tree associated with the destination
            try:
                st = self.i2t[ip]
                logging.debug('%s: IP registered: %s (shared)' % (topo, addrstr(ip)))
            except KeyError:
                st = IterableSubnetTree()
                self.i2t[ip] = st
                logging.debug('%s: IP registered: %s' % (topo, addrstr(ip)))

            # register which sources this topo wants packets from
            for ps in topo.get_source_filters():
                if st.has_exact(ps):
                    # another topo has both this dst IP and the same source filter
                    st[ps].append(topo)
                    logging.debug('%s: Source filter: %s (shared)' % (topo, ps))
                else:
                    st[ps] = [topo]
                    logging.debug('%s: Source filter: %s' % (topo, ps))
Пример #3
0
    def register_topology(self, topo):
        """Registers a topology with the resolver."""
        if not topo.has_gateway():
            return  # it is isolated from the real world

        for mac in topo.get_my_mac_addrs():
            try:
                self.m2t[mac].append(topo)
                logging.debug('%s: MAC registered: %s (shared)' %
                              (topo, addrstr(mac)))
            except KeyError:
                self.m2t[mac] = [topo]
                logging.debug('%s: MAC registered: %s' % (topo, addrstr(mac)))

        for ip in topo.get_all_ip_addrs_in_my_ip_block():
            # get the source filtering tree associated with the destination
            try:
                st = self.i2t[ip]
                logging.debug('%s: IP registered: %s (shared)' %
                              (topo, addrstr(ip)))
            except KeyError:
                st = IterableSubnetTree()
                self.i2t[ip] = st
                logging.debug('%s: IP registered: %s' % (topo, addrstr(ip)))

            # register which sources this topo wants packets from
            for ps in topo.get_source_filters():
                if st.has_exact(ps):
                    # another topo has both this dst IP and the same source filter
                    st[ps].append(topo)
                    logging.debug('%s: Source filter: %s (shared)' %
                                  (topo, ps))
                else:
                    st[ps] = [topo]
                    logging.debug('%s: Source filter: %s' % (topo, ps))
Пример #4
0
    def handle_packet_from_outside(self, packet):
        """Forwards packet to the appropriate simulation, if any."""
        if len(packet) < 14:
            return # too small to even have an Ethernet header

        # determine which topology(ies) should receive this packet
        pkt = ProtocolHelper.Packet(packet)
        if pkt.is_valid_ipv4():
            topos = self.resolver.resolve_ip(pkt.ip_dst, pkt.ip_src)
            str_addr = 'dst=%s src=%s' % (addrstr(pkt.ip_dst), addrstr(pkt.ip_src))
            rewrite_dst_mac = True
        elif pkt.is_dst_mac_broadcast():
            return # ignore broadcasts
        else:
            topos = self.resolver.resolve_mac(pkt.mac_dst)
            str_addr = 'dst=%s' % addrstr(pkt.mac_dst)
            rewrite_dst_mac = False

        # forward the packet to the appropriate topology(ies)
        if topos:
            logging.debug('sniffed raw packet to %s (topology %s): %s' %
                          (str_addr, ','.join([str(t.id) for t in topos]), pktstr(packet)))
            for topo in topos:
                topo.create_job_for_incoming_packet(packet, rewrite_dst_mac)
                self.job_available_event.set()
Пример #5
0
    def unregister_topology(self, topo):
        """Unregisters a topology with the resolver."""
        if not topo.has_gateway():
            return  # it is isolated from the real world

        for mac in topo.get_my_mac_addrs():
            try:
                topos = self.m2t[mac]
                try:
                    topos.remove(topo)
                    if not topos:
                        del self.m2t[mac]
                except ValueError:
                    logging.error('%s: missing topo in list for %s' %
                                  (topo, addrstr(mac)))
            except KeyError:
                logging.error('%s: missing topo list for %s' %
                              (topo, addrstr(mac)))

        for ip in topo.get_all_ip_addrs_in_my_ip_block():
            # get the source filtering tree associated with the destination
            try:
                st = self.i2t[ip]
            except KeyError:
                logging.error('%s: missing subnet tree for %s' %
                              (topo, addrstr(ip)))
                continue

            # unregister which sources this topo wants packets from
            for ps in topo.get_source_filters():
                try:
                    topos = st.get_exact(ps)
                    try:
                        topos.remove(
                            topo)  # remove this topology's registration
                        if not topos:
                            del st[ps]
                    except ValueError:
                        logging.error(
                            '%s: missing topology in source filter %s for %s' %
                            (topo, ps, addrstr(ip)))
                except KeyError:
                    logging.error('%s: missing source filter %s for %s' %
                                  (topo, ps, addrstr(ip)))

            # if no topologies are still mapped to this IP, then delete this empty tree
            if len(st) == 0:
                del self.i2t[ip]
Пример #6
0
    def __make_response_dynamic_body(body, pkt):
        """Replaces tags in a given response body with the proper values from
        the request packet. This is used in order to see what request ip and
        port the HTTPServer sees (useful for testing NAT)."""

        body = body.replace('%SRC_PORT%', portstr(pkt.tcp_src_port))
        body = body.replace('%SRC_IP%', addrstr(pkt.ip_src))
        return body
Пример #7
0
    def __make_response_dynamic_body(body, pkt):
        """Replaces tags in a given response body with the proper values from
        the request packet. This is used in order to see what request ip and
        port the HTTPServer sees (useful for testing NAT)."""

        body = body.replace('%SRC_PORT%', portstr(pkt.tcp_src_port))
        body = body.replace('%SRC_IP%', addrstr(pkt.ip_src))
        return body
Пример #8
0
 def resolve_mac(self, dst_mac):
     """Resolves a dst MAC address to a list of topologies to which the
     packet to this dst should be forwarded."""
     try:
         topos = self.m2t[dst_mac]
         logging.debug('MAC %s resolved to topo %s' % (addrstr(dst_mac), ','.join([str(t.id) for t in topos])))
         return topos
     except KeyError:
         # logging.debug('Ignoring packet to MAC %s' % addrstr(dst_mac))
         return [] # no topology has this MAC address
Пример #9
0
    def unregister_topology(self, topo):
        """Unregisters a topology with the resolver."""
        if not topo.has_gateway():
            return # it is isolated from the real world

        for mac in topo.get_my_mac_addrs():
            try:
                topos = self.m2t[mac]
                try:
                    topos.remove(topo)
                    if not topos:
                        del self.m2t[mac]
                except ValueError:
                    logging.error('%s: missing topo in list for %s' % (topo, addrstr(mac)))
            except KeyError:
                logging.error('%s: missing topo list for %s' % (topo, addrstr(mac)))

        for ip in topo.get_all_ip_addrs_in_my_ip_block():
            # get the source filtering tree associated with the destination
            try:
                st = self.i2t[ip]
            except KeyError:
                logging.error('%s: missing subnet tree for %s' % (topo, addrstr(ip)))
                continue

            # unregister which sources this topo wants packets from
            for ps in topo.get_source_filters():
                try:
                    topos = st.get_exact(ps)
                    try:
                        topos.remove(topo) # remove this topology's registration
                        if not topos:
                            del st[ps]
                    except ValueError:
                        logging.error('%s: missing topology in source filter %s for %s' % (topo, ps, addrstr(ip)))
                except KeyError:
                    logging.error('%s: missing source filter %s for %s' % (topo, ps, addrstr(ip)))

            # if no topologies are still mapped to this IP, then delete this empty tree
            if len(st) == 0:
                del self.i2t[ip]
Пример #10
0
 def resolve_mac(self, dst_mac):
     """Resolves a dst MAC address to a list of topologies to which the
     packet to this dst should be forwarded."""
     try:
         topos = self.m2t[dst_mac]
         logging.debug(
             'MAC %s resolved to topo %s' %
             (addrstr(dst_mac), ','.join([str(t.id) for t in topos])))
         return topos
     except KeyError:
         # logging.debug('Ignoring packet to MAC %s' % addrstr(dst_mac))
         return []  # no topology has this MAC address
Пример #11
0
    def resolve_ip(self, dst_ip, src_ip=None):
        """Resolves a src and dst IP address pair to a list of topologies to
        which the packet with this src and dst should be forwarded.  All
        parameters should be in network byte ordered byte strings.

        @param dst_ip_or_mac  The destination IP or MAC address.

        @param src_ip  The source IP this packet is from.  It may be omitted
                       when the source IP is not known (e.g., L2 traffic).

        @return An empty list is returned if no mapping exists.  Otherwise, the
                returned list is all topologies which should receive the packet.
        """
        try:
            st = self.i2t[dst_ip]
        except KeyError:
            # logging.debug('Ignoring packet to %s' % addrstr(dst_ip))
            return [] # no topology has this IP address

        # If there is no source IP, return all of the topologies which have this
        # destination address.
        if not src_ip:
            logging.debug('No source IP given.  All topos mapped by %s: %s' % \
                          (addrstr(dst_ip), ','.join([str(t.id) for t in st.values()])))
            return st.values()

        # Figure out which topology is interested in packets from this source.
        try:
            topos = st[src_ip]
            logging.debug('IP pair resolved to topo: (%s->%s) -> %s' % \
                          (addrstr(src_ip), addrstr(dst_ip), ','.join([str(t.id) for t in topos])))
            return topos
        except KeyError:
            logging.debug('IP pair ignored (not interested in the source): %s->%s' % \
                          (addrstr(src_ip), addrstr(dst_ip)))
            return [] # nobody is interested in packets from this source
Пример #12
0
    def resolve_ip(self, dst_ip, src_ip=None):
        """Resolves a src and dst IP address pair to a list of topologies to
        which the packet with this src and dst should be forwarded.  All
        parameters should be in network byte ordered byte strings.

        @param dst_ip_or_mac  The destination IP or MAC address.

        @param src_ip  The source IP this packet is from.  It may be omitted
                       when the source IP is not known (e.g., L2 traffic).

        @return An empty list is returned if no mapping exists.  Otherwise, the
                returned list is all topologies which should receive the packet.
        """
        try:
            st = self.i2t[dst_ip]
        except KeyError:
            # logging.debug('Ignoring packet to %s' % addrstr(dst_ip))
            return []  # no topology has this IP address

        # If there is no source IP, return all of the topologies which have this
        # destination address.
        if not src_ip:
            logging.debug('No source IP given.  All topos mapped by %s: %s' % \
                          (addrstr(dst_ip), ','.join([str(t.id) for t in st.values()])))
            return st.values()

        # Figure out which topology is interested in packets from this source.
        try:
            topos = st[src_ip]
            logging.debug('IP pair resolved to topo: (%s->%s) -> %s' % \
                          (addrstr(src_ip), addrstr(dst_ip), ','.join([str(t.id) for t in topos])))
            return topos
        except KeyError:
            logging.debug('IP pair ignored (not interested in the source): %s->%s' % \
                          (addrstr(src_ip), addrstr(dst_ip)))
            return []  # nobody is interested in packets from this source
Пример #13
0
    def handle_packet(self, intf, packet):
        """Responses to ARP requests (as appropriate) and forwards IP packets."""
        if len(packet) < 14:
            logging.debug('%s ignoring packet which is too small: %dB' % (self.di(), len(packet)))
            return

        logging.debug('%s handling packet: %s' % (self.di(), pktstr(packet)))
        pkt = ProtocolHelper.Packet(packet)
        if pkt.mac_dst != intf.mac and not (pkt.is_valid_arp() and pkt.mac_dst=='\xFF\xFF\xFF\xFF\xFF\xFF'):
            logging.debug('%s dropping packet (not to my mac addr %s): %s' % (self.di(), addrstr(intf.mac), pktstr(packet)))
        elif pkt.is_valid_ipv4():
            self.handle_ipv4_packet(intf, pkt)
        elif pkt.is_valid_arp():
            self.handle_arp_packet(intf, pkt)
        else:
            logging.debug('%s discarding packet which is neither valid IPv4 nor ARP' % self.di())
Пример #14
0
 def __get_intf_str(intf):
     str_link = intf.link.str_half(intf) if intf.link else ''
     return '%s={%s,%s}%s' % (intf.name, addrstr(intf.ip), addrstr(intf.mac), str_link)
Пример #15
0
    def handle_packet(self, intf, packet):
        """Responses to ARP requests (as appropriate) and forwards IP packets."""
        if len(packet) < 14:
            logging.debug('%s ignoring packet which is too small: %dB' % (self.di(), len(packet)))
            return

        logging.debug('%s handling packet: %s' % (self.di(), pktstr(packet)))
        pkt = ProtocolHelper.Packet(packet)
        if pkt.mac_dst != intf.mac and not (pkt.is_valid_arp() and pkt.mac_dst=='\xFF\xFF\xFF\xFF\xFF\xFF'):
            logging.debug('%s dropping packet (not to my mac addr %s): %s' % (self.di(), addrstr(intf.mac), pktstr(packet)))
        elif pkt.is_valid_ipv4():
            self.handle_ipv4_packet(intf, pkt)
        elif pkt.is_valid_arp():
            self.handle_arp_packet(intf, pkt)
        else:
            logging.debug('%s discarding packet which is neither valid IPv4 nor ARP' % self.di())
Пример #16
0
 def __get_intf_str(intf):
     str_link = intf.link.str_half(intf) if intf.link else ''
     return '%s={%s,%s}%s' % (intf.name, addrstr(intf.ip), addrstr(intf.mac), str_link)