def on_frame(self, raw): frame = Frame(raw) self.mac2port[frame.src_mac] = self if frame.dst_mac in (frame.src_mac, MAC_Loopback): return try: port = self.mac2port[frame.dst_mac] except KeyError: self.flood(frame) else: port.send(frame)
def on_frame(self, raw): frame = Frame(raw) if frame.ethertype == Frame.EtherType.ARP: self.arp.process(frame.payload) elif frame.ethertype == Frame.EtherType.IPv4: self.on_ipv4(frame, interface=self) elif frame.ethertype in (Frame.EtherType.Raw, ): self.report( 'unsupported frame type "{}", ignored', Frame.EtherType[frame.ethertype], ) else: self.report('unknown frame type, ignored')
def send_packet(self, data, dst_ip, ethertype): try: dst_mac = self.ip2mac[dst_ip] except KeyError: self.pending_packets[dst_ip].append((data, ethertype)) self.arp.query(dst_ip) else: frame = Frame( dst_mac=dst_mac, src_mac=self.mac, ethertype=ethertype, payload=data, ) self.send_frame(frame)
def _send_pending_packets(self, ip, mac): ps = self.pending_packets[ip] if not ps: return self.report('send pending {} packet(s) for {}', len(ps), ip) while ps: p, ethertype = ps.popleft() f = Frame( ethertype=ethertype, dst_mac=mac, src_mac=self.mac, payload=p, ) self.send_frame(f)
def on_frame(self, raw): frame = Frame(raw) self.mac2port[frame.src_mac] = self self.host.report('{} <= {}', self, frame.src_mac) if frame.dst_mac in (frame.src_mac, MAC_Loopback): self.host.report('loopback frame, ignored') return try: port = self.mac2port[frame.dst_mac] except KeyError: self.flood(frame) else: self.host.report('{} -> {}', self.index, port.index) port.send(frame)
def arp_respond(self, request): packet = ARP( oper=ARP.Oper.IAm, src_ip=self.ip, src_mac=self.mac, dst_ip=request.src_ip, dst_mac=request.src_mac, ) frame = Frame( dst_mac=request.src_mac, src_mac=self.mac, ethertype=Frame.EtherType.ARP, payload=packet.raw, ) self.pending_frames.append(frame)
def arp_query(self, dst_ip): packet = ARP( oper=ARP.Oper.WhoIs, src_ip=self.ip, src_mac=self.mac, dst_ip=dst_ip, dst_mac=MAC_Invalid, ) frame = Frame( dst_mac=MAC_Broadcast, src_mac=self.mac, ethertype=Frame.EtherType.ARP, payload=packet.raw, ) self.pending_frames.append(frame)
def send_packet(self, packet, ethertype=Frame.EtherType.IPv4): try: dst_ip = packet.dst_ip dst_mac = self.ip2mac[dst_ip] except KeyError: self.pending_packets[dst_ip].append((packet, ethertype)) self.arp_query(dst_ip) else: frame = Frame( dst_mac=dst_mac, src_mac=self.mac, ethertype=ethertype, payload=packet.raw, ) self.pending_frames.append(frame)
def query(self, dst_ip): pdu = PDU( oper=PDU.Oper.WhoIs, src_ip=self.host.ip, src_mac=self.host.mac, dst_ip=dst_ip, dst_mac=MAC_Invalid, ) frame = Frame( dst_mac=MAC_Broadcast, src_mac=self.host.mac, ethertype=Frame.EtherType.ARP, payload=pdu.raw, ) self.send_frame(frame) self.report('Who has {}? Tell {}', pdu.dst_ip, pdu.src_ip)
def run(self): while True: self.routes.remove_expired_entries() for iport in self.ports: try: raw = iport.recv(block=False) except Empty: continue frame = Frame(raw) self.routes.register(frame.src, iport) oports = self.routes.get(frame.dst, exclude=iport) for oport in oports: try: oport.send(raw, block=False) except Full: mint.report('frame dropped {}', repr(raw)) mint.elapse(1)
def send_packet(self, data, dst_ip, ethertype): if not dst_ip: self.report('invalid dst_ip {}, ignored', dst_ip) return try: dst_mac = self.ip2mac[dst_ip] except KeyError: self.pending_packets[dst_ip].append((data, ethertype)) self.arp.query(dst_ip) else: frame = Frame( dst_mac=dst_mac, src_mac=self.mac, ethertype=ethertype, payload=data, ) self.send_frame(frame)
def on_arp(self, raw): arp = ARP(raw) self.ip2mac[arp.src_ip] = arp.src_mac if arp.oper == ARP.Oper.IAm: packets = self.pending_packets[arp.src_ip] while packets: packet, ethertype = packets.popleft() frame = Frame( ethertype=ethertype, dst_mac=arp.src_mac, src_mac=self.mac, payload=packet.raw, ) self.pending_frames.append(frame) return if arp.dst_ip != self.ip: return if arp.oper == ARP.Oper.WhoIs: self.arp_respond(arp)
def respond(self, request): pdu = PDU( oper=PDU.Oper.IAm, src_ip=self.host.ip, src_mac=self.host.mac, dst_ip=request.src_ip, dst_mac=request.src_mac, ) frame = Frame( dst_mac=request.src_mac, src_mac=self.host.mac, ethertype=Frame.EtherType.ARP, payload=pdu.raw, ) self.send_frame(frame) self.report( 'tell {} that {} is {}', pdu.dst_ip, pdu.src_mac, pdu.src_ip, )
def on_frame(self, raw): frame = Frame(raw) if frame.ethertype == Frame.EtherType.ARP: self.on_arp(frame.payload) elif frame.ethertype == Frame.EtherType.IPv4: self.on_ipv4(frame)