def handle_packet_from_outside(data): logging.debug('--------------------------------------------------') logging.debug('--------------------------------------------------') logging.debug('got packet: %s' % pktstr(data)) pkt = Packet(data) if pkt.is_tcp() and pkt.is_valid_tcp(): logging.debug('passing on tcp packet ...') tcp_conn = server.handle_tcp(pkt) if tcp_conn: tcp_pts = tcp_conn.get_packets_to_send() if tcp_pts: for tcp, data in tcp_pts: eth = pkt.get_reversed_eth() ip = pkt.get_reversed_ip(new_ttl=64, new_tlen=pkt.ip_hlen + len(tcp) + len(data)) p = eth + ip + Packet.cksum_tcp_hdr(ip, tcp, data) + data logging.debug('sending packet: %s' % pktstr(p)) try: raw_socket.send(p) except socket.error: logging.exception('failed to send packet') sys.exit(-1) else: logging.debug('no packets to send back')
def got_packet(self, pkt): """Handles packets received as a result of this tap. If the packet is an echo reply to an echo request we sent, then True is returned.""" # log the packet if requested if self.print_recv_packets: print pktstr(pkt, noop=False) if self.log_fp: pcap_write_packet(self.log_fp, pkt) # see if this was an echo reply we were waiting for if self.num_replies_outstanding > 0: return self.__check_for_echo_reply(pkt) return False
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()
def handle_packet(self, incoming_intf, packet): """Forwards to the user responsible for handling packets for this virtual node""" if self.conn is not None: logging.debug('%s got packet on %s - forwarding to VNS client: %s' % (self.di(), incoming_intf.name, pktstr(packet))) self.topo.stats.note_pkt_to_client(len(packet)) self.conn.send(VNSPacket(incoming_intf.name, packet))
def handle_packet(self, incoming_intf, packet): """Forward each received packet to every interface except the one it was received on""" logging.debug('%s got packet on %s - forwarding it out all other ports: %s' % (self.di(), incoming_intf.name, pktstr(packet))) for intf in self.interfaces: if intf.name != incoming_intf.name: self.send_packet(intf, packet)
def handle_http_request(self, intf, pkt): """Forward the received packet from an HTTP client to the web server.""" tcp_conn = self.http_server.handle_tcp(pkt) if tcp_conn: tcp_pts = tcp_conn.get_packets_to_send() if tcp_pts: for tcp, data in tcp_pts: eth = pkt.get_reversed_eth() ip = pkt.get_reversed_ip(new_ttl=64, new_tlen=pkt.ip_hlen+len(tcp)+len(data)) pkt_out = eth + ip + Packet.cksum_tcp_hdr(ip, tcp, data) + data logging.debug('%s sending packet from HTTP server: %s' % (self, pktstr(pkt_out))) intf.link.send_to_other(intf, pkt_out)
def handle_arp_packet(self, intf, pkt): """Respond to arp if it is a request for the mac address of intf's IP.""" if pkt.arp_type != '\x00\x01': # only handle ARP REQUESTs logging.debug('%s ignoring ARP which is not a request' % self.di()) return # is the ARP request asking about THIS interface on broadcast dha? if pkt.dpa==intf.ip and pkt.mac_dst=='\xFF\xFF\xFF\xFF\xFF\xFF': # send it back to the requester (reverse src/dst, copy in our mac addr) reply_eth = pkt.get_reversed_eth(new_mac_dst=intf.mac) reply_arp = pkt.arp[0:7] + '\x02' + intf.mac + intf.ip + pkt.sha + pkt.spa reply = reply_eth + reply_arp logging.debug('%s replying to ARP request: %s' % (self.di(), pktstr(reply))) self.send_packet(intf, reply)
def handle_packet_from_outside(data): logging.debug('--------------------------------------------------') logging.debug('--------------------------------------------------') logging.debug('got packet: %s' % pktstr(data)) pkt = Packet(data) if pkt.is_tcp() and pkt.is_valid_tcp(): logging.debug('passing on tcp packet ...') tcp_conn = server.handle_tcp(pkt) if tcp_conn: tcp_pts = tcp_conn.get_packets_to_send() if tcp_pts: for tcp, data in tcp_pts: eth = pkt.get_reversed_eth() ip = pkt.get_reversed_ip(new_ttl=64, new_tlen=pkt.ip_hlen+len(tcp)+len(data)) p = eth + ip + Packet.cksum_tcp_hdr(ip, tcp, data) + data logging.debug('sending packet: %s' % pktstr(p)) try: raw_socket.send(p) except socket.error: logging.exception('failed to send packet') sys.exit(-1) else: logging.debug('no packets to send back')
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())
def handle_packet_from_client(self, conn, pkt_msg): """Sends the specified message out the specified port on the node controlled by conn. If conn does not control a node, then a KeyError is raised. If conn's node does not have an interface with the specified name then an error message is returned. Otherwise, True is returned.""" departure_intf_name = pkt_msg.intf_name n = self.clients[conn] for intf in n.interfaces: if intf.name == departure_intf_name: logging.debug('%s: client sending packet from %s out %s: %s' % (self, n.name, intf.name, pktstr(pkt_msg.ethernet_frame))) self.stats.note_pkt_from_client(len(pkt_msg.ethernet_frame)) n.send_packet(intf, pkt_msg.ethernet_frame) return True # failed to find the specified interface fmt = 'bad packet request: invalid interface: %s' return fmt % ((n.name, departure_intf_name),)
def handle_ipv4_packet_to_self(self, intf, pkt): """Called when a IP packet for on of our interfaces is received on intf. eth holds the Ethernet frame bytes and ip holds the IP packet bytes. This implementation replies with an echo reply or protocol unreachable as appropriate.""" if pkt.ip_proto == '\x01': icmp = pkt.ip_payload if icmp[0] == '\x08': # echo request new_eth = pkt.get_reversed_eth() new_ip = pkt.get_reversed_ip(new_ttl=64) new_icmp = ProtocolHelper.Packet.cksum_icmp_pkt('\x00' + icmp[1:]) # change to echo reply type echo_reply = new_eth + new_ip + new_icmp logging.debug('%s replying to echo request: %s' % (self.di(), pktstr(echo_reply))) self.send_packet(intf, echo_reply) else: logging.debug('%s ignoring ICMP which is not an echo request' % self.di()) else: self.handle_non_icmp_ip_packet_to_self(intf, pkt)
def handle_packet_from_client(self, conn, pkt_msg): """Sends the specified message out the specified port on the node controlled by conn. If conn does not control a node, then a KeyError is raised. If conn's node does not have an interface with the specified name then an error message is returned. Otherwise, True is returned.""" departure_intf_name = pkt_msg.intf_name n = self.clients[conn] for intf in n.interfaces: if intf.name == departure_intf_name: logging.debug('%s: client sending packet from %s out %s: %s' % (self, n.name, intf.name, pktstr(pkt_msg.ethernet_frame))) self.stats.note_pkt_from_client(len(pkt_msg.ethernet_frame)) n.send_packet(intf, pkt_msg.ethernet_frame) return True # failed to find the specified interface fmt = 'bad packet request: invalid interface: %s' return fmt % (n.name, departure_intf_name)
def handle_non_icmp_ip_packet_to_self(self, intf, pkt): """Handles IP packets which are not ICMP packets by replying with a protocol unreachable ICMP message.""" dst_unreach = pkt.generate_complete_icmp_dst_unreach() logging.debug('%s sending dst unreachable in response to non-ICMP IP packet: %s' % (self.di(), pktstr(dst_unreach))) self.send_packet(intf, dst_unreach)
def create_job_for_incoming_packet(self, packet, rewrite_dst_mac): """Enqueues a job for handling this packet with handle_incoming_packet().""" try: self.job_queue.put_nowait(lambda : self.handle_incoming_packet(packet, rewrite_dst_mac)) except Queue.Full: logging.debug("Queue full for topology %s, dropping incoming packet: %s" % (str(self), pktstr(packet)))
def handle_packet(self, incoming_intf, packet): """Discard all received packets.""" logging.debug('%s got packet on %s - black-holing it: %s' % (self.di(), incoming_intf.name, pktstr(packet)))
def __str__(self): return 'PACKET from %s: %s' % (TINodePortHeader.__str__(self), pktstr(self.ethernet_frame))
def send_packets(self): """Send any waiting packets""" if self.intf and self.pkt: for (_, tcp_conn) in self.http_server.connections.iteritems(): if tcp_conn and not tcp_conn.dead: tcp_pts = tcp_conn.get_packets_to_send() for tcp, data in tcp_pts: eth = self.pkt.get_reversed_eth() ip = self.pkt.get_reversed_ip(new_ttl=64, new_tlen=self.pkt.ip_hlen+len(tcp)+len(data)) pkt_out = eth + ip + Packet.cksum_tcp_hdr(ip, tcp, data) + data logging.debug('%s sending packet from HTTP server: %s' % (self, pktstr(pkt_out))) self.intf.link.send_to_other(self.intf, pkt_out)
def handle_packet(self, incoming_intf, packet): """Forwards an IP packet from the simulated topology to the network.""" if len(packet) >= 34 and packet[12:14] == '\x08\x00': dst_ip = packet[30:34] if not MAY_FORWARD_TO_PRIVATE_IPS and self.__is_private_address(dst_ip): logging.debug('%s ignoring IP packet to private address space: %s' % (self.di(), inet_ntoa(dst_ip))) return if len(packet) >= 42 and packet[12:14] == '\x08\06' and self.topo.gw_intf_to_first_hop: pkt = ProtocolHelper.Packet(packet) if pkt.is_arp_reply() and pkt.dha == self.topo.gw_intf_to_first_hop.mac: logging.debug('%s: handling ARP reply from first hop to gateway' % self.di()) self.topo.update_arp_translation(pkt.sha) return # forward packet out to the real network if self.raw_socket: try: logging.debug('%s sending packet out to the real world: %s' % (self.di(), pktstr(packet))) self.topo.stats.note_pkt_from_topo(len(packet)) self.raw_socket.send(packet) except socket.error: # this is recoverable - the network may come back up log_exception(logging.WARN, 'unable to forward packet to the real network')
def handle_packet(self, incoming_intf, packet): """Forwards an IP packet from the simulated topology to the network.""" if len(packet) >= 34 and packet[12:14] == '\x08\x00': dst_ip = packet[30:34] if not MAY_FORWARD_TO_PRIVATE_IPS and self.__is_private_address(dst_ip): logging.debug('%s ignoring IP packet to private address space: %s' % (self.di(), inet_ntoa(dst_ip))) return if len(packet) >= 42 and packet[12:14] == '\x08\06' and self.topo.gw_intf_to_first_hop: pkt = ProtocolHelper.Packet(packet) if pkt.is_arp_reply() and pkt.dha == self.topo.gw_intf_to_first_hop.mac: logging.debug('%s: handling ARP reply from first hop to gateway' % self.di()) self.topo.update_arp_translation(pkt.spa, pkt.sha) return # forward packet out to the real network if self.raw_socket: try: logging.debug('%s sending packet out to the real world: %s' % (self.di(), pktstr(packet))) self.topo.stats.note_pkt_from_topo(len(packet)) self.raw_socket.send(packet) except socket.error: # this is recoverable - the network may come back up log_exception(logging.WARN, 'unable to forward packet to the real network')