def _handle_ICMP_Reply(self, dpid, ethernet_packet, srcip, dstip, icmpType): ICMP_packet = icmp() ICMP_packet.type = icmpType if icmpType == pkt.TYPE_ECHO_REPLY: ICMP_packet.payload = ethernet_packet.find('icmp').payload elif icmpType == pkt.TYPE_DEST_UNREACH: oriIp = ethernet_packet.find('ipv4') d = oriIp.pack() d = d[:oriIp.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d ICMP_packet.payload = d IP_packet = ipv4() IP_packet.protocol = IP_packet.ICMP_PROTOCOL IP_packet.srcip = dstip IP_packet.dstip = srcip IP_packet.payload = ICMP_packet e = ethernet() e.src = ethernet_packet.dst if (srcip in subnet1 and self.routerIP[dpid] in subnet1) or (srcip in subnet2 and self.routerIP[dpid] in subnet2) or (srcip in subnet2 and self.routerIP[dpid] in subnet): e.dst = ethernet_packet.src else: gatewayIP = IPAddr(self._find_gatewayIP(IP_packet.dstip)) e.dst = self.arpTable[dpid][gatewayIP] e.type = e.IP_TYPE e.payload = IP_packet msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = self.routingTable[dpid][srcip] self.connections[dpid].send(msg) log.debug("Router {0}: {1} ping router at {2}".format(dpid, srcip, dstip))
def handleIcmpRequest(self, dpid, p, srcip, dstip, icmpType): pIcmp = icmp() pIcmp.type = icmpType if icmpType == pkt.TYPE_ECHO_REPLY: pIcmp.payload = p.find('icmp').payload elif icmpType == pkt.TYPE_DEST_UNREACH: oriIp = p.find('ipv4') d = oriIp.pack() d = d[:oriIp.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d pIcmp.payload = d pIp = ipv4() pIp.protocol = pIp.ICMP_PROTOCOL pIp.srcip = dstip pIp.dstip = srcip e = ethernet() e.src = p.dst e.dst = p.src e.type = e.IP_TYPE pIp.payload = pIcmp e.payload = pIp msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = self.routingTable[dpid][srcip] self.connections[dpid].send(msg) log.debug("dpid %d: IP %s ping router at %s" % (dpid, str(srcip), str(dstip)))
def ICMP_Handler(self, packet, packet_in): ethernet_frame = packet ip_packet = packet.payload icmp_request_packet = ip_packet.payload # ICMP Echo Request (8) -> ICMP Echo Reply (0) if icmp_request_packet.type == 8: icmp_echo_reply_packet = icmp() icmp_echo_reply_packet.code = 0 icmp_echo_reply_packet.type = 0 icmp_echo_reply_packet.payload = icmp_request_packet.payload ip = ipv4() ip.srcip = ip_packet.dstip ip.dstip = ip_packet.srcip ip.protocol = ipv4.ICMP_PROTOCOL ip.payload = icmp_echo_reply_packet ether = ethernet() ether.type = ethernet.IP_TYPE ether.src = ethernet_frame.dst ether.dst = ethernet_frame.src ether.payload = ip self.resend_packet(ether, packet_in.in_port) log.debug("%s ICMP ECHO REPLY SENT!" % self.dpid)
def icmp_unreach(self, dpid, packet, inport): icmp_pkt = icmp() #icmp_pkt = pkt.unreach() #icmp_pkt.payload = packet.find("icmp").payload #print str(icmp_pkt.payload.pack().encode('hex')) icmp_pkt.type = 3 icmp_pkt.code = 0 orig_ip = packet.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d icmp_pkt.payload = d #print str(d.encode('hex')) ip_pkt = ipv4() srcip = IPAddr(self.fakeways[dpid - 1][0]) ip_pkt.srcip = IPAddr(self.fakeways[dpid - 1][0]) ip_pkt.dstip = packet.payload.srcip ip_pkt.protocol = ip_pkt.ICMP_PROTOCOL ip_pkt.set_payload(icmp_pkt) #print str(ip_pkt.payload) e = ethernet(type=ethernet.IP_TYPE, src=self.arpTable[dpid][srcip].mac, dst=packet.src) #print str(self.arpTable[dpid][ip_pkt.srcip].mac) e.set_payload(ip_pkt) action = of.ofp_action_output(port=inport) po = of.ofp_packet_out(actions=action, data=e.pack()) core.openflow.sendToDPID(dpid, po)
def handle_ICMP_packets (self, packet, packet_in): """ Controller may receive ICMP echo (ping) requests for the router, which it should respond to. """ ppacket = packet.payload icmp_request_packet = ppacket.payload # make new icmp reply to the received icmp request if icmp_request_packet.type == 8: # (8 type number is for icmp request) icmp_echo_reply_packet = icmp() icmp_echo_reply_packet.code = 0 icmp_echo_reply_packet.type = 0 # (0 type number is for icmp reply) icmp_echo_reply_packet.payload = icmp_request_packet.payload # make ipv4 header ip = ipv4() # set it's fields ip.srcip = ppacket.dstip ip.dstip = ppacket.srcip ip.protocol = ipv4.ICMP_PROTOCOL ip.payload = icmp_echo_reply_packet # make the new packet to send newPacket = ethernet() # set it's fields newPacket.type = ethernet.IP_TYPE newPacket.src = ethernet_frame.dst newPacket.dst = ethernet_frame.src newPacket.payload = ip self.resend_packet(newPacket, packet_in.in_port)
def icmp_message(self, dpid, p, srcip, dstip, icmp_type,event): p_icmp = icmp() p_icmp.type = icmp_type if icmp_type == pkt.TYPE_ECHO_REPLY: p_icmp.payload = p.find('icmp').payload elif icmp_type == pkt.TYPE_DEST_UNREACH: #print dir(p.next) orig_ip = p.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d # network, unsigned short, unsigned short p_icmp.payload = d #print dir(p) #print type(p.payload) p_ip = ipv4() p_ip.protocol = p_ip.ICMP_PROTOCOL p_ip.srcip = dstip # srcip, dstip in the argument is from the ping p_ip.dstip = srcip e = ethernet() e.src = p.dst e.dst = p.src e.type = e.IP_TYPE p_ip.payload = p_icmp e.payload = p_ip msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = self.routing[dpid][srcip] event.connection.send(msg)
def _handle_icmp_reply(self, dpid, p, srcip, dstip, icmp_type): p_icmp = icmp() p_icmp.type = icmp_type if icmp_type == pkt.TYPE_ECHO_REPLY: p_icmp.payload = p.find('icmp').payload elif icmp_type == pkt.TYPE_DEST_UNREACH: orig_ip = p.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d p_icmp.payload = d p_ip = ipv4() p_ip.protocol = p_ip.ICMP_PROTOCOL p_ip.srcip = dstip p_ip.dstip = srcip e = ethernet() e.src = p.dst e.dst = p.src e.type = e.IP_TYPE p_ip.payload = p_icmp e.payload = p_ip msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = self.routingTable[dpid][srcip] self.connections[dpid].send(msg) log.debug('DPID : IP %s pings router at %s, send icmp reply'% (str(srcip), str(dstip)))
def _send_ip_packet(self, protocol, dstip, dsthw, payload, _out_port): ipp = ipv4() ipp.protocol = protocol ipp.srcip = self.my_ip ipp.dstip = dstip ipp.set_payload(payload) self._send_ethernet_packet(packet_type=ethernet.IP_TYPE, _src=self.my_mac, _dst=dsthw, payload=ipp, out_port=_out_port)
def send_icmp(self, tp, code, dest_ip, dest_mac, dest_port, orig_packet): # Should be able to send echo reply (tp=0,code=0), # destination unreachable (tp=3,code=0(network unreachable)/1(host unreachable)/3(port unreachable)), # TTL expired (tp=11,code=0) msg = None if tp == 0: p = orig_packet.payload while p is not None and not isinstance(p, echo): p = p.next if p is None: return r = echo(id=p.id, seq=p.seq) r.set_payload(p.next) msg = icmp(type=0, code=0) msg.set_payload(r) elif tp == 3: msg = icmp() msg.type = 3 msg.code = code d = orig_packet.payload.pack() d = d[:orig_packet.payload.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d msg.payload = d elif tp == 11: msg = icmp() msg.type = 11 msg.code = 0 d = orig_packet.payload.pack() d = d[:orig_packet.payload.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d msg.payload = d # Make the IP packet around it ipp = ipv4() ipp.protocol = ipp.ICMP_PROTOCOL ipp.srcip = IPAddr(dest_port.ip) ipp.dstip = IPAddr(dest_ip) # Ethernet around that... e = ethernet() e.src = EthAddr(dest_port.mac) e.dst = EthAddr(dest_mac) e.type = e.IP_TYPE # Hook them up... ipp.payload = msg e.payload = ipp # send this packet to the switch log.debug('router {}; Sending ICMP TYPE {}; code {}; dest_ip {}; output_port {}'.format(self.connection.dpid, tp, code, dest_ip, dest_port.id)) self.send_packet(None, e, dest_port.id, of.OFPP_NONE)
def _ip_handler(self, ipInfo, etherInfo, out_port): # Build ip Packet ipv4Pkt = ipv4() ipv4Pkt.srcip = ipInfo.srcip ipv4Pkt.dstip = ipInfo.dstip ipv4Pkt.protocol = ipInfo.protocol ipv4Pkt.payload = ipInfo.payload # Build Ether Packet etherPkt = ethernet(src = etherInfo.src, dst = etherInfo.dst, type = etherInfo.pType) etherPkt.payload = ipv4Pkt self.resend_packet(etherPkt, out_port) return True
def _handle_icmp_reply(self, dpid, p, srcip, dstip, icmp_type): pic = icmp() pic.type = icmp_type if icmp_type == pkt.TYPE_ECHO_REPLY: pic.payload = p.find('icmp').payload elif icmp_type == pkt.TYPE_DEST_UNREACH: orig_ip = p.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d pic.payload = d #p_ip = ipv4() ipv4().protocol = ipv4().ICMP_PROTOCOL ipv4().srcip = dstip ipv4().dstip = srcip e = ethernet() e.src = p.dst if (srcip in Subnet1 and self.routerIP[dpid] in Subnet1) or (srcip in Subnet2 and self.routerIP[dpid] in Subnet2): e.dst = p.src else: gatewayip = IPAddr('10.0.%d.1' % (3-dpid)) e.dst = self.arpTable[dpid][gatewayip] e.type = e.IP_TYPE p_ip.payload = p_icmp e.payload = p_ip msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = self.routingTable[dpid][srcip] self.connections[dpid].send(msg) log.debug('DPID %d: IP %s pings router at %s, generating icmp reply', dpid, str(srcip), str(dstip))
def _ip_handler(self, hwsrc, hwdst, srcip, dstip, packet_out = None, protocol = ipv4.TCP_PROTOCOL): # Build Ip Packet ipv4Pkt = ipv4() ipv4Pkt.srcip = srcip ipv4Pkt.dstip = dstip ipv4Pkt.ttl = 64 ipv4Pkt.payload = packet_out ipv4Pkt.protocol = protocol # Build Ether Packet etherPkt = ethernet(src = hwsrc, dst = hwdst, type = ethernet.IP_TYPE) etherPkt.payload = ipv4Pkt self.resend_packet(etherPkt, self.table.ip_to_port[dstip]) return True
def _create_icmp_unreachable(self, ip_packet, inport): p = icmp() p.type = pkt.TYPE_DEST_UNREACH data = ip_packet.pack() data = data[:ip_packet.hl * 4 + 8] data = struct.pack("!HH", 0, 0) + data p.payload = data p_ip = ipv4() p_ip.protocol = p_ip.ICMP_PROTOCOL p_ip.srcip = self.port_list[inport].ip p_ip.dstip = ip_packet.srcip p_ip.payload = p return p_ip
def isValidIpPacket(self,event): # ipv4_packet = event.parsed.find("ipv4") ipv4_packet = event.parsed.find("ipv4") # Do more processing of the IPv4 packet src_ip = ipv4_packet.srcip dst_ip = ipv4_packet.dstip if(ipv4_packet.csum!=ipv4_packet.checksum()): print "Ip packet checksum not macthing" return False if(ipv4_packet.ttl<=1): if(dst_ip==self.IPAddr or dst_ip.toStr()=='255.255.255.255'): print "My Packet accept at ",self.IPAddr print ipv4_packet if(packet.payload.protocol==packet.payload.ICMP_PROTOCOL): self.handle_icmp(event) return False print "TTL Invalid" icmp_rep = icmp() icmp_rep.type = 11 # TYPE_TIME_EXCEED #icmp_rep.code=0 icmp_rep.next=unreach() # icmp_rep.next.seq=packet.payload.next.next.seq # icmp_rep.next.id=packet.payload.next.next.id # icmp_rep.next.raw=packet.payload.next.next.raw # Show the client that it's actually the me rep=ipv4() rep.srcip=self.IPAddr rep.dstip=ipv4_packet.srcip rep.next=icmp_rep rep.protocol=ipv4_packet.ICMP_PROTOCOL eth = ethernet() eth.dst = event.parsed.src eth.src = self.EthAddr eth.set_payload(rep) eth.type = ethernet.IP_TYPE msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = event.port self.connection.send(msg) return False if(ipv4_packet.iplen<20): print "Length Invalid" return False # len > min_len return True
def GenerateTrace(): acl_trace = open(r'..\Data\acl3_4k_rules.txt_trace') trace = acl_trace.readlines() packets = [] for line in trace: tum = line.split() src = long2ip(long(tum[0])) dst = long2ip(long(tum[1])) packet = ethernet(src=EthAddr("00:00:00:00:00:01"), payload=ipv4(srcip=IPAddr(src), dstip=IPAddr(dst), payload=udp(srcport=1234, dstport=53, payload="haha"))) packets.append(packet) return packets
def get_udp_resp(self, src_port, dst_port, src_ip, dst_ip, src_mac, dst_mac, content): udp_resp = udp() udp_resp.srcport = src_port udp_resp.dstport = dst_port udp_resp.payload = content ipv4_pkt = ipv4() ipv4_pkt.srcip = src_ip ipv4_pkt.dstip = dst_ip ipv4_pkt.protocol = ipv4.UDP_PROTOCOL ipv4_pkt.payload = udp_resp ether = ethernet() ether.type = ethernet.IP_TYPE ether.dst = dst_mac ether.src = src_mac ether.payload = ipv4_pkt return ether
def ICMP_Unreachable(self, packet, packet_in): icmp_reply_unreachable = icmp() icmp_reply_unreachable.code = 0 icmp_reply_unreachable.type = 3 icmp_reply_unreachable.payload = packet.payload.payload.payload ip_reply_unreachable = ipv4() ip_reply_unreachable.srcip = packet.payload.dstip ip_reply_unreachable.dstip = packet.payload.srcip ip_reply_unreachable.protocol = ipv4.ICMP_PROTOCOL ip_reply_unreachable.payload = icmp_reply_unreachable ether_packet = ethernet() ether_packet.type = ethernet.IP_TYPE ether_packet.src = packet.dst ether_packet.dst = packet.src ether_packet.payload = ip_reply_unreachable self.resend_packet(ether_packet, packet_in.in_port) log.debug('ICMP reply for unreachable packet has sent')
def ICMP_Request_Router_local(self, packet, packet_in): icmp_reply = icmp() icmp_reply.code = 0 icmp_reply.type = 0 icmp_reply.payload = packet.payload.payload.payload ip_reply = ipv4() ip_reply.srcip = packet.payload.dstip ip_reply.dstip = packet.payload.srcip ip_reply.protocol = ipv4.ICMP_PROTOCOL ip_reply.payload = icmp_reply ether_packet = ethernet() ether_packet.type = ethernet.IP_TYPE ether_packet.src = packet.dst ether_packet.dst = packet.src ether_packet.payload = ip_reply self.resend_packet(ether_packet, packet_in.in_port) log.debug('ICMP/TCP/UDP reply has sent')
def handle_icmp(self,event): print "ICMP Packet Arrived" packet=event.parsed src_mac = packet.src dst_mac = packet.dst ipv4_packet = event.parsed.find("ipv4") src_ip = ipv4_packet.srcip dst_ip = ipv4_packet.dstip if packet.payload.next.type==8: print "handing" icmp_rep = icmp() # icmp_rep.type = 3 icmp_rep.next=echo() icmp_rep.next.seq=packet.payload.next.next.seq icmp_rep.next.id=packet.payload.next.next.id icmp_rep.next.raw=packet.payload.next.next.raw # Show the client that it's actually the me rep=ipv4() rep.srcip=self.IPAddr rep.dstip=src_ip rep.next=icmp_rep rep.protocol=packet.payload.ICMP_PROTOCOL eth = ethernet() eth.dst = packet.src eth.src = self.EthAddr eth.set_payload(rep) eth.type = ethernet.IP_TYPE msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = event.port self.connection.send(msg) print "done handing" return if packet.payload.next.type==3: if packet.payload.next.code==1: print "Destination Host Unreachable" if packet.payload.next.code==0: print "Destination Network Unreachable" return
def receive(self, interface, packet): """ Process an incoming packet from a switch Called by PatchPanel """ if packet.type == ethernet.ARP_TYPE: arp_reply = self._check_arp_reply(packet) if arp_reply is not None: self.log.info("received valid arp packet on " "interface %s: %s" % (interface.name, str(packet))) self.send(interface, arp_reply) return arp_reply else: self.log.info("received invalid arp packet on " "interface %s: %s" % (interface.name, str(packet))) return None elif (self.send_capabilities and packet.type == ethernet.IP_TYPE and packet.next.protocol == ipv4.ICMP_PROTOCOL): # Temporary hack: if we receive a ICMP packet, send a TCP RST to signal # to POX that we do want to revoke the capability for this flow. See # pox/pox/forwarding/capabilities_manager.py self.log.info("Sending RST on interface %s: in " "response to: %s" % (interface.name, str(packet))) t = tcp() tcp.RST = True i = ipv4() i.protocol = ipv4.TCP_PROTOCOL i.srcip = interface.ips[0] i.dstip = packet.next.srcip i.payload = t ether = ethernet() ether.type = ethernet.IP_TYPE ether.src = interface.hw_addr ether.dst = packet.src ether.payload = i self.send(interface, ether) self.log.info("Received packet %s on interface " "%s" % (str(packet), interface.name))
def send_lsu(self): pl=str(self.seq)+':' self.seq=self.seq+1 for i in self.neighbours.values(): pl=pl+i.toStr()+':' for i in self.hosts: pl=pl+i+':' rep=ipv4() rep.next=pl global _lsu_tos rep.tos=_lsu_tos rep.srcip=self.IPAddr eth = ethernet() eth.src = self.EthAddr eth.set_payload(rep) eth.type = ethernet.IP_TYPE msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_ALL)) self.connection.send(msg)
def parsePacket(self, event): # data = event.ofp.data ethernet_packet = ethernet(raw=data) # print str(ethernet_packet) if ethernet_packet.type != ethernet.VLAN_TYPE: log.debug("WEIRD: Got packet without VLAN") return data, ethernet_packet, None, None vlan_packet = vlan(raw=data[ethernet.MIN_LEN:]) ethernet_packet.set_payload(vlan_packet) # print str(vlan_packet) ip_packet = None if vlan_packet.eth_type == ethernet.ARP_TYPE: ip_packet = arp(raw=data[IP_START:]) vlan_packet.set_payload(ip_packet) elif vlan_packet.eth_type == ethernet.IP_TYPE: ip_packet = ipv4(raw=data[IP_START:]) vlan_packet.set_payload(ip_packet) elif vlan_packet.eth_type == ethernet.IPV6_TYPE: pass else: log.debug("GOT soemthing that wasn't expecting: " + vlan_packet.eth_type) tcp_packet = None if ip_packet and vlan_packet.eth_type == ethernet.IP_TYPE: if ip_packet.protocol == ipv4.TCP_PROTOCOL: tcp_raw = ip_packet.raw[ipv4.MIN_LEN:] tcp_packet = tcp(raw=tcp_raw) ip_packet.set_payload(tcp_packet) payload = tcp_packet.payload # print "TCP = " + str(tcp_packet) + " PAYLOAD = " + payload # print str(ip_packet) # ip_packet.dump() return data, ethernet_packet, vlan_packet, ip_packet, tcp_packet
def _generate_icmp_reply(self, dpid, p, srcip, dstip, icmp_type): p_icmp = icmp() p_icmp.type = icmp_type if icmp_type == pkt.TYPE_ECHO_REPLY: p_icmp.payload = p.find('icmp').payload elif icmp_type == pkt.TYPE_DEST_UNREACH: #print dir(p.next) orig_ip = p.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d # network, unsigned short, unsigned short p_icmp.payload = d p_ip = ipv4() p_ip.protocol = p_ip.ICMP_PROTOCOL p_ip.srcip = dstip # srcip, dstip in the argument is from the ping p_ip.dstip = srcip e = ethernet() e.src = p.dst if is_same_subnet(srcip, self.routerIP[dpid]): e.dst = p.src else: gatewayip = dpid_to_ip(3 - dpid) e.dst = self.arpTable[dpid][gatewayip] e.type = e.IP_TYPE p_ip.payload = p_icmp e.payload = p_ip msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = self.routingTable[dpid][srcip] self.connections[dpid].send(msg) log.debug( 'DPID %d: IP %s pings router at %s, generating icmp reply with code %d...', dpid, str(srcip), str(dstip), icmp_type)
def _generate_icmp_reply(self, dpid, p, srcip, dstip, icmp_type): p_icmp = icmp() p_icmp.type = icmp_type if icmp_type == pkt.TYPE_ECHO_REPLY: p_icmp.payload = p.find('icmp').payload elif icmp_type == pkt.TYPE_DEST_UNREACH: #print dir(p.next) orig_ip = p.find('ipv4') d = orig_ip.pack() d = d[:orig_ip.hl * 4 + 8] d = struct.pack("!HH", 0, 0) + d # network, unsigned short, unsigned short p_icmp.payload = d p_ip = ipv4() p_ip.protocol = p_ip.ICMP_PROTOCOL p_ip.srcip = dstip # srcip, dstip in the argument is from the ping p_ip.dstip = srcip e = ethernet() e.src = p.dst if is_same_subnet(srcip, self.routerIP[dpid]): e.dst = p.src else: gatewayip = dpid_to_ip( 3-dpid ) e.dst = self.arpTable[dpid][gatewayip] e.type = e.IP_TYPE p_ip.payload = p_icmp e.payload = p_ip msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = self.routingTable[dpid][srcip] self.connections[dpid].send(msg) log.debug('DPID %d: IP %s pings router at %s, generating icmp reply with code %d...', dpid, str(srcip), str(dstip), icmp_type)
def reponseToClient(self, dhcp_pckt, ip_relay, ip_dst, mac_dst, port_switch): ip_dst = '255.255.255.255' if ip_dst=='0.0.0.0' else ip_dst udp = udp(srcport = 67, dstport = 68) udp.set_payload(dhcp_pckt) ip = ipv4(protocol=17, srcip = ip_relay, dstip = ip_dst) ip.set_payload(udp) e= ethernet(type= 0x0800, src = 'aa:aa:aa:bb:bb:bb', dst = mac_dst) e.set_payload(ip) msg= of.ofp_packet_out() msg.data = e.pack() action=of.ofp_action_output( port=of.OFPP_IN_PORT ) msg.actions.append(action) msg.in_port= port_switch self.connection.send(msg)
def _router_handle_icmp(self, event): # NOTE handles ECHO messages for now only packet = event.parsed ipPacket = packet.next icmpPacket = ipPacket.next replied = False if icmpPacket.type == TYPE_ECHO_REQUEST: for port in self.ports: if port.ip == ipPacket.dstip: # ping reply reply = icmp() reply.type = TYPE_ECHO_REPLY reply.payload = icmpPacket.payload # seq, id, etc. # ip packet i = ipv4() i.protocol = i.ICMP_PROTOCOL i.srcip = ipPacket.dstip i.dstip = ipPacket.srcip i.payload = reply # ethernet e = ethernet(type = ethernet.IP_TYPE, src = packet.dst, dst = packet.src) e.payload = i # openflow msg msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output( port = of.OFPP_IN_PORT)) msg.data = e.pack() msg.in_port = event.port self.connection.send(msg) # break the for-loop replied = True break if not replied: # this must be other's ping self._router_handle_ipv4(event)
def _send_icmp_reply(self, dpid, p, srcip, dstip, icmpType, event): pktIcmp = pkt.icmp() # TYPE_ECHO_REQUEST = 8, TYPE_DEST_UNREACH = 3, TYPE_ECHO_REPLY = 0 if icmpType == pkt.TYPE_ECHO_REPLY: pktIcmp.payload = p.find('icmp').payload elif icmpType == pkt.TYPE_DEST_UNREACH: pktIcmp.type = pkt.TYPE_DEST_UNREACH unreachMsg = pkt.unreach() unreachMsg.payload = p.payload pktIcmp.payload = unreachMsg # Make IP header pktIp = ipv4() pktIp.protocol = pktIp.ICMP_PROTOCOL pktIp.srcip = dstip pktIp.dstip = srcip # Ethernet header eth = ethernet() eth.src = p.dst eth.dst = p.src eth.type = eth.IP_TYPE # Hook them up pktIp.payload = pktIcmp # ICMP encapsulated in IP packet eth.payload = pktIp # IP packet encapsulated in ethernet frame # Send it back to the input port msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.data = eth.pack() msg.in_port = self.routingTable[dpid][srcip] event.connection.send(msg) log.debug('DPID %d: IP %s pings %s, icmp reply with type %d', dpid, str(srcip), str(dstip), icmpType) log.debug('(type 0: reply, type 3: unreach, type 8: request)')
def _send_icmp_reply(self, dpid, p, srcip, dstip, icmpType, event): pktIcmp = pkt.icmp() # TYPE_ECHO_REQUEST = 8, TYPE_DEST_UNREACH = 3, TYPE_ECHO_REPLY = 0 if icmpType == pkt.TYPE_ECHO_REPLY: pktIcmp.payload = p.find('icmp').payload elif icmpType == pkt.TYPE_DEST_UNREACH: pktIcmp.type = pkt.TYPE_DEST_UNREACH unreachMsg = pkt.unreach() unreachMsg.payload = p.payload pktIcmp.payload = unreachMsg # Make IP header pktIp = ipv4() pktIp.protocol = pktIp.ICMP_PROTOCOL pktIp.srcip = dstip pktIp.dstip = srcip # Ethernet header eth = ethernet() eth.src = p.dst eth.dst = p.src eth.type = eth.IP_TYPE # Hook them up pktIp.payload = pktIcmp # ICMP encapsulated in IP packet eth.payload = pktIp # IP packet encapsulated in ethernet frame # Send it back to the input port msg = of.ofp_packet_out() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.data = eth.pack() msg.in_port = self.routingTable[dpid][srcip] event.connection.send(msg) log.debug('DPID %d: IP %s pings %s, icmp reply with type %d', dpid, str(srcip), str(dstip), icmpType) log.debug('(type 0: reply, type 3: unreach, type 8: request)')
def _handle_timer(self): # print "sending IP packet from R"+str(self.connection.dpid) rep=ipv4() global _hello_tos if self.ct==6: self.send_lsu() self.ct=0 self.ct=self.ct+1 rep.tos=_hello_tos rep.srcip=self.IPAddr; eth = ethernet() eth.src = self.EthAddr; eth.set_payload(rep) eth.type = ethernet.IP_TYPE msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_ALL)) self.connection.send(msg) # CHECK outdated self.neighbours tm=time.time() sz=self.times.keys() global NBRTIMEOUT,LSUTIMEOUT for port in sz: if tm-self.times[port]>NBRTIMEOUT: sys.stderr.write(str(tm-self.times[port])+" REMOVED "+self.neighbours[port].toStr()+"\n") self.times.pop(port,0) self.G.remove_node(self.neighbours[port]) self.neighbours.pop(port,0) for ip in self.times2.keys(): if tm-self.times2[ip]>LSUTIMEOUT and self.G.has_node(ip): self.G.remove_node(ip) sys.stderr.write(str(tm-self.times2[ip])+" REMOVED "+ip.toStr()+"\n") if len(self.times.keys())<len(sz): self.send_lsu()
def handle_ipPacket(self,event): # handle broad cast ip also print "IP packet Received at R"+str(event.dpid) packet=event.parsed src_mac = packet.src dst_mac = packet.dst if dst_mac!=self.EthAddr and dst_mac!=EthAddr('ff:ff:ff:ff:ff:ff'): return if(not self.isValidIpPacket(event)): return ipv4_packet = event.parsed.find("ipv4") # Do more processing of the IPv4 packet src_ip = ipv4_packet.srcip dst_ip = ipv4_packet.dstip if(dst_ip==self.IPAddr or dst_ip.toStr()=='255.255.255.255'): print "My Packet accept at ",self.IPAddr print ipv4_packet if(packet.payload.protocol==packet.payload.ICMP_PROTOCOL): self.handle_icmp(event) else: nxt=self.FindNextHopInterface(dst_ip.toStr()) if(nxt[0]==-1): # need to send an icmp packet # print "No Route to Host" # Create ARP reply icmp_rep = icmp() icmp_rep.type = 3 icmp_rep.code= nxt[2] icmp_rep.next=unreach() # icmp_rep.next.seq=packet.payload.next.next.seq # icmp_rep.next.id=packet.payload.next.next.id # icmp_rep.next.raw=packet.payload.next.next.raw # Show the client that it's actually the me rep=ipv4() rep.srcip=self.IPAddr rep.dstip=src_ip rep.next=icmp_rep rep.protocol=packet.payload.ICMP_PROTOCOL eth = ethernet() eth.dst = packet.src eth.src = self.EthAddr eth.set_payload(rep) eth.type = ethernet.IP_TYPE msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = event.port self.connection.send(msg) print "icmp reply DONE" else: NextHopIP=nxt[0] Interface=nxt[1][-1] # payload=packet.payload.pa/yload # payload of IP packet # create a empty IP packet # ipv4_packet_out=ipv4_packet ipv4_packet.ttl=ipv4_packet.ttl-1 # Create the Ethernet packet eth = ethernet() eth.type = ethernet.IP_TYPE if IPAddr(NextHopIP) in self.arp_table: eth.dst = self.arp_table[IPAddr(NextHopIP)] eth.src = self.EthAddr eth.set_payload(ipv4_packet) # msg is the "packet out" message. Now giving this packet special properties msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = int(Interface))) msg.in_port = event.port self.connection.send(msg) else: arp_rep = arp() arp_rep.opcode = arp.REQUEST # Show the client that it's actually the me arp_rep.hwsrc = self.EthAddr arp_rep.hwdst = EthAddr('ff:ff:ff:ff:ff:ff') #arp_rep.hwdst = 'ff:ff:ff:ff:ff:ff' arp_rep.protosrc = self.IPAddr arp_rep.protodst = IPAddr(NextHopIP) # Create the Ethernet packet eth1 = ethernet() eth1.type = ethernet.ARP_TYPE eth1.dst = EthAddr('ff:ff:ff:ff:ff:ff') eth1.src = self.EthAddr eth1.set_payload(arp_rep) # Send the ARP reply to client # msg is the "packet out" message. Now giving this packet special properties msg = of.ofp_packet_out() msg.data = eth1.pack() msg.actions.append(of.ofp_action_output(port = int(Interface))) msg.in_port = event.port self.connection.send(msg) eth.src = self.EthAddr eth.set_payload(ipv4_packet_out) self.que.append((eth,int(Interface),event.port))
vlan_packet.id = vlan_id vlan_packet.pcp = 0 vlan_packet.eth_type = ethernet_packet.type V = vlan_packet.hdr('') # Grab the rest of the packet = R R = ethernet_packet.raw[ethernet.MIN_LEN:] # Construct E + V + R new_raw = E + V + R new_ethernet_packet = ethernet(new_raw) return new_ethernet_packet if __name__ == "__main__": eth = ethernet() eth.dst = EthAddr("01:02:03:04:05:06") eth.src = EthAddr("11:12:13:14:15:16") eth.type = ethernet.IP_TYPE ip = ipv4() ip.srcip = IPAddr("128.99.98.97") ip.dstip = IPAddr("128.89.8.87") joint_eth = ethernet(eth.hdr('') + ip.hdr('')) print "JOINT = " + str(joint_eth) print "IP = " + str(ipv4(joint_eth.raw[ethernet.MIN_LEN:])) joint_eth_vlan = add_vlan_to_packet(joint_eth, 1000) print "JOINT_V = " + str(joint_eth_vlan) print "V = " + str(vlan(joint_eth_vlan.raw[ethernet.MIN_LEN:])) print "IP = " + str(ipv4(joint_eth_vlan.raw[ethernet.MIN_LEN+vlan.MIN_LEN:]))
def _handle_SRPacketOut(self, event): msg = of.ofp_packet_out() new_packet = event.pkt if (event.port == 3): #out going packet, need to go through NAT packet = ethernet(raw=event.pkt) if (packet.type == ethernet.IP_TYPE): #print "in SRPacketOut" #print packet ip_pkt = ipv4(raw=event.pkt[ethernet.MIN_LEN:]) if (ip_pkt.protocol == ipv4.UDP_PROTOCOL and ip_pkt.next.dstport == 53): src_ip = ip_pkt.srcip.toStr() if (src_ip in IP_SETTING.values()): ip_pkt.srcip = IPAddr( INTERNAL_NAME[NAME_SETTING[src_ip]]) ip_pkt.csum = ip_pkt.checksum() packet.next = ip_pkt #new_packet = packet.pack() #event.pkt[ethernet.MIN_LEN:ipv4.hl] = ip_pkt.tyhdr() #ipp = ip_pkt #event.pkt[ethernet.MIN_LEN:ip_pkt.hl] = struct.pack('!BBHHHBBHII', (ipp.v << 4) + ipp.hl, ipp.tos, ipp.iplen, ipp.id, (ipp.flags << 13) | ipp.frag, ipp.ttl, ipp.protocol, ipp.csum, ipp.srcip.toUnsigned(), ipp.dstip.toUnsigned()) #npkt = ipv4(raw=event.pkt[ethernet.MIN_LEN:]) #print npkt # udp_pkt= ip_pkt.next # dns_pkt = udp_pkt.next # print dns_pkt # d = dns() # u = udp() # ipp = ipv4() # ipp.protocol = ipp.UDP_PROTOCOL # ipp.srcip = IPAddr(INTERNAL_NAME[NAME_SETTING[src_ip]]) # ipp.dstip = ip_pkt.dstip # e = ethernet() # e.src = packet.src # e.dst = packet.dst # e.type = e.IP_TYPE # ipp.payload = udp_pkt # e.payload = ipp # new_packet = e.pack() else: src_ip = ip_pkt.srcip.toStr() #print ip_pkt.srcip if (src_ip in IP_SETTING.values()): # print "change IP src\n" ip_pkt.srcip = IPAddr( INTERNAL_NAME[NAME_SETTING[src_ip]]) # print ip_pkt.srcip ip_pkt.csum = ip_pkt.checksum() ip_pkt.raw = None packet.next = ip_pkt if (ip_pkt.protocol == ipv4.ICMP_PROTOCOL): icmp_pkt = ip_pkt.next icmp_pkt.raw = None if (icmp_pkt.type == 3): ip_hdr = icmp_pkt.next.next ip_hdr.dstip = IPAddr( INTERNAL_NAME[NAME_SETTING[src_ip]]) #print "Replace icmp MSG IP addr !!!!\n" #print icmp_pkt new_packet = packet.pack() elif (packet.type == ethernet.ARP_TYPE): if (packet.next.opcode == arp.REQUEST): # print "get a arp request" arp_req = packet.next src_ip = arp_req.protosrc.toStr() if (src_ip in IP_SETTING.values()): # print "change arp request src \n" arp_req.protosrc = IPAddr( INTERNAL_NAME[NAME_SETTING[src_ip]]) # print arp_req.protosrc arp_req.raw = None packet.next = arp_req new_packet = packet.pack() msg.actions.append(of.ofp_action_output(port=event.port)) msg.buffer_id = -1 msg.in_port = of.OFPP_NONE msg.data = new_packet #log.debug("SRServer catch SRPacketOut event, fwd_pkt=%r, port=%s\n" % (event.pkt, event.port)) self.connection.send(msg)
def _handle_SRPacketOut(self, event): msg = of.ofp_packet_out() new_packet = event.pkt if(event.port == 1): #out going packet, need to go through NAT packet = ethernet(raw = event.pkt) if( packet.type == ethernet.IP_TYPE ): #print "in SRPacketOut" #print packet ip_pkt = ipv4(raw=event.pkt[ethernet.MIN_LEN:]) if( ip_pkt.protocol == ipv4.UDP_PROTOCOL and ip_pkt.next.dstport == 53): src_ip = ip_pkt.srcip.toStr() if( src_ip in IP_SETTING.values()): ip_pkt.srcip = IPAddr(INTERNAL_NAME[NAME_SETTING[src_ip]]) ip_pkt.csum = ip_pkt.checksum() packet.next = ip_pkt #new_packet = packet.pack() #event.pkt[ethernet.MIN_LEN:ipv4.hl] = ip_pkt.tyhdr() #ipp = ip_pkt #event.pkt[ethernet.MIN_LEN:ip_pkt.hl] = struct.pack('!BBHHHBBHII', (ipp.v << 4) + ipp.hl, ipp.tos, ipp.iplen, ipp.id, (ipp.flags << 13) | ipp.frag, ipp.ttl, ipp.protocol, ipp.csum, ipp.srcip.toUnsigned(), ipp.dstip.toUnsigned()) #npkt = ipv4(raw=event.pkt[ethernet.MIN_LEN:]) #print npkt # udp_pkt= ip_pkt.next # dns_pkt = udp_pkt.next # print dns_pkt # d = dns() # u = udp() # ipp = ipv4() # ipp.protocol = ipp.UDP_PROTOCOL # ipp.srcip = IPAddr(INTERNAL_NAME[NAME_SETTING[src_ip]]) # ipp.dstip = ip_pkt.dstip # e = ethernet() # e.src = packet.src # e.dst = packet.dst # e.type = e.IP_TYPE # ipp.payload = udp_pkt # e.payload = ipp # new_packet = e.pack() else: src_ip = ip_pkt.srcip.toStr() #print ip_pkt.srcip if(src_ip in IP_SETTING.values()): # print "change IP src\n" ip_pkt.srcip = IPAddr(INTERNAL_NAME[NAME_SETTING[src_ip]]) # print ip_pkt.srcip ip_pkt.csum = ip_pkt.checksum() ip_pkt.raw = None packet.next = ip_pkt if ( ip_pkt.protocol == ipv4.ICMP_PROTOCOL ): icmp_pkt = ip_pkt.next icmp_pkt.raw = None if( icmp_pkt.type == 3 ): ip_hdr = icmp_pkt.next.next ip_hdr.dstip = IPAddr(INTERNAL_NAME[NAME_SETTING[src_ip]]) #print "Replace icmp MSG IP addr !!!!\n" #print icmp_pkt new_packet = packet.pack() elif( packet.type == ethernet.ARP_TYPE ): if( packet.next.opcode == arp.REQUEST ): # print "get a arp request" arp_req = packet.next src_ip = arp_req.protosrc.toStr() if( src_ip in IP_SETTING.values()): # print "change arp request src \n" arp_req.protosrc = IPAddr(INTERNAL_NAME[NAME_SETTING[src_ip]]) # print arp_req.protosrc arp_req.raw = None packet.next = arp_req new_packet = packet.pack() msg.actions.append(of.ofp_action_output(port=event.port)) msg.buffer_id = -1 msg.in_port = of.OFPP_NONE msg.data = new_packet #log.debug("SRServer catch SRPacketOut event, fwd_pkt=%r, port=%s\n" % (event.pkt, event.port)) self.connection.send(msg)
def handle_ipPacket(self,event): # handle broad cast ip also # print "IP packet Received at R"+str(event.dpid) packet=event.parsed if(packet is None): print "error" print event src_mac = packet.src dst_mac = packet.dst ipv4_packet = event.parsed.next if(ipv4_packet is None): print "error" print event # Do more processing of the IPv4 packet src_ip = ipv4_packet.srcip dst_ip = ipv4_packet.dstip global _hello_tos, _lsu_tos if ipv4_packet.tos == _hello_tos: print "HELLO at R"+str(event.dpid)+" from "+src_ip.toStr() self.neighbours[event.port]=src_ip self.times[event.port]=time.time() self.G.add_edge(self.IPAddr,src_ip) self.send_lsu() return if ipv4_packet.tos == _lsu_tos: if src_ip==self.IPAddr: return print "LSU at R"+str(event.dpid)+" from "+src_ip.toStr() self.times2[src_ip]=time.time() pl=ipv4_packet.next lst=pl.split(':')[:-1] if src_ip in self.seqnum.keys() and self.seqnum[src_ip]>=int(pl[0]): return self.seqnum[src_ip]=int(pl[0]) ed=[i for i in self.G.edges() if i[0]==src_ip] try: self.G.remove_edges_from(ed) except: pass for i in lst[1:]: self.G.add_edge(src_ip,IPAddr(i)) eth = ethernet() eth.src = self.EthAddr eth.set_payload(ipv4_packet) eth.type = ethernet.IP_TYPE msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_ALL)) self.connection.send(msg) return if dst_mac!=self.EthAddr and dst_mac!=EthAddr('ff:ff:ff:ff:ff:ff'): return if(not self.isValidIpPacket(event)): return if(dst_ip==self.IPAddr or dst_ip.toStr()=='255.255.255.255'): if(packet.payload.protocol==packet.payload.ICMP_PROTOCOL): self.handle_icmp(event) else: nxt=self.FindNextHopInterface(dst_ip.toStr()) if(nxt[0]==-1): # need to send an icmp packet # print "No Route to Host" # Create ARP reply icmp_rep = icmp() icmp_rep.type = 3 icmp_rep.code= nxt[2] icmp_rep.next=unreach() # icmp_rep.next.seq=packet.payload.next.next.seq # icmp_rep.next.id=packet.payload.next.next.id # icmp_rep.next.raw=packet.payload.next.next.raw # Show the client that it's actually the me rep=ipv4() rep.srcip=self.IPAddr rep.dstip=src_ip rep.next=icmp_rep rep.protocol=packet.payload.ICMP_PROTOCOL eth = ethernet() eth.dst = packet.src eth.src = self.EthAddr eth.set_payload(rep) eth.type = ethernet.IP_TYPE msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = event.port self.connection.send(msg) print "icmp reply DONE" else: NextHopIP=nxt[0] Interface=nxt[1][-1] payload=packet.payload.payload # payload of IP packet # create a empty IP packet ipv4_packet_out=ipv4_packet ipv4_packet_out.ttl=ipv4_packet_out.ttl-1 # Create the Ethernet packet eth = ethernet() eth.type = ethernet.IP_TYPE if IPAddr(NextHopIP) in self.arp_table: eth.dst = self.arp_table[IPAddr(NextHopIP)] eth.src = self.EthAddr eth.set_payload(ipv4_packet_out) # msg is the "packet out" message. Now giving this packet special properties msg = of.ofp_packet_out() msg.data = eth.pack() msg.actions.append(of.ofp_action_output(port = int(Interface))) msg.in_port = event.port self.connection.send(msg) else: arp_rep = arp() arp_rep.opcode = arp.REQUEST # Show the client that it's actually the me arp_rep.hwsrc = self.EthAddr arp_rep.hwdst = EthAddr('ff:ff:ff:ff:ff:ff') #arp_rep.hwdst = 'ff:ff:ff:ff:ff:ff' arp_rep.protosrc = self.IPAddr arp_rep.protodst = IPAddr(NextHopIP) # Create the Ethernet packet eth1 = ethernet() eth1.type = ethernet.ARP_TYPE eth1.dst = EthAddr('ff:ff:ff:ff:ff:ff') eth1.src = self.EthAddr eth1.set_payload(arp_rep) # Send the ARP reply to client # msg is the "packet out" message. Now giving this packet special properties msg = of.ofp_packet_out() msg.data = eth1.pack() msg.actions.append(of.ofp_action_output(port = int(Interface))) msg.in_port = event.port self.connection.send(msg) eth.src = self.EthAddr eth.set_payload(ipv4_packet_out) self.que.append((eth,int(Interface),event.port))
def _handle_PacketIn (self, event): dpid = event.connection.dpid inport = event.port packet = copy.deepcopy(event.parsed) if not packet.parsed: log.warning("%i %i ignoring unparsed packet", dpid, inport) return if dpid not in self.arpTable: # New switch -- create an empty table self.arpTable[dpid] = {} for fake in self.fakeways: self.arpTable[dpid][IPAddr(fake)] = Entry(of.OFPP_NONE, dpid_to_mac(dpid)) # store the mac, ip info of the DNS SERVER into arpTable self.arpTable[dpid][IPAddr(IP_OF_DNS_SERVER)]=Entry(6633, EthAddr(MAC_OF_DNS_SERVER)) if packet.type == ethernet.LLDP_TYPE: # Ignore LLDP packets return p = packet.find('dns') if p is not None and p.parsed: # Get dstName of the DNS Query dstname = ''; for question in p.questions: dstname = question.name log.debug("DNS Query msg from %s: asking ip address for %s", packet.next.srcip, dstname) # Learn or update port/MAC info if packet.next.srcip in self.arpTable[dpid]: if self.arpTable[dpid][packet.next.srcip] != (inport, packet.src): log.info("%i %i RE-learned %s", dpid, inport, packet.next.srcip) else: log.debug("%i %i learned %s", dpid, inport, str(packet.next.srcip)) self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src) # generate random virtual ip for internal node n = random.randint(128, 254) vip = "10.0.0." + str(n) #add the srcip and virtual destination ip pair into srcip_dstip_map self.srcip_dstvip_map[str(packet.next.srcip)] = vip # forming answer answer = dns.rr(dstname, 1, 1, 5, len(vip), IPAddr(vip)) # write dns reply msg d = dns() d.questions = p.questions d.answers.append(answer) d.authorities = [] d.additional =[] d.id = p.id d.qr = True # dns reply d.opcode = 0 # standard d.aa = False d.tc = False d.rd = False d.ra = False d.z = False d.ad = False d.cd = False d.rcode = 0 e = ethernet(type=ethernet.IP_TYPE, src=MAC_OF_DNS_SERVER, dst=str(packet.src)) ip = ipv4(srcip = IPAddr(IP_OF_DNS_SERVER)) ip.dstip = packet.next.srcip ip.protocol = ip.UDP_PROTOCOL u = udp() u.srcport = dns.SERVER_PORT # get srcport from the packet and set it to the udp's dstport m = packet.find("udp") m.parsed u.dstport = m.srcport u.payload = d ip.payload = u e.payload = ip msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_nw_addr.set_dst(packet.next.srcip)) msg.actions.append(of.ofp_action_dl_addr.set_dst(packet.src)) msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) log.debug(" DNS reply msg has been sent to %s: %s's ip address is %s" % (str(packet.next.srcip), dstname, vip)) elif isinstance(packet.next, ipv4): log.debug("IPv4 msg: %i %i IP %s => %s", dpid,inport, packet.next.srcip,packet.next.dstip) # Send any waiting packets... self._send_lost_buffers(dpid, packet.next.srcip, packet.src, inport) print "Have sent lost buffers" # Learn or update port/MAC info if packet.next.srcip in self.arpTable[dpid]: if self.arpTable[dpid][packet.next.srcip] != (inport, packet.src): log.info("%i %i RE-learned %s", dpid,inport,packet.next.srcip) else: log.debug("%i %i learned %s", dpid,inport,str(packet.next.srcip)) self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src) srcaddr = packet.next.srcip dstaddr = packet.next.dstip if(dstaddr in self.vipList): self.srcip_dstvip_map[srcaddr] = dstaddr dstaddr = IPAddr(REAL_IP_OF_INTERNAL_HOST) if dstaddr in self.arpTable[dpid]: # We have info about what port to send it out on... prt = self.arpTable[dpid][dstaddr].port mac = self.arpTable[dpid][dstaddr].mac # Try to forward icmpmsg = packet.find("icmp") icmpmsg.parsed # icmp echo reply from internal host if icmpmsg.type == 0 and srcaddr == IPAddr(REAL_IP_OF_INTERNAL_HOST): log.info("ICMP echo reply msg from %s to %s", srcaddr, packet.next.dstip) if prt == inport: log.warning("%i %i not sending packet for %s back out of the " + "input port" % (dpid, inport, str(dstaddr))) else: log.debug("%i %i installing flow for %s => %s out port %i" % (dpid, inport, packet.next.srcip, dstaddr, prt)) # add flow entry msg = of.ofp_flow_mod(command = of.OFPFC_ADD) msg.match.dl_type = 0x0800 #ipv4 msg.match.nw_src = REAL_IP_OF_INTERNAL_HOST msg.match.nw_dst = dstaddr # change the srcip to virtual ip msg.actions.append(of.ofp_action_nw_addr.set_src(IPAddr(self.srcip_dstvip_map[dstaddr]))) msg.actions.append(of.ofp_action_dl_addr.set_dst(mac)) msg.actions.append(of.ofp_action_output(port = prt)) event.connection.send(msg) log.info("ICMP echo reply flow entry for internal node to %s has been installed", packet.next.dstip) # icmp echo reply for internal host elif icmpmsg.type == 8 and dstaddr == IPAddr(REAL_IP_OF_INTERNAL_HOST): log.info("ICMP echo request msg from %s to %s", packet.next.srcip, packet.next.dstip) if prt == inport: log.warning("%i %i not sending packet for %s back out of the " + "input port" % (dpid, inport, str(dstaddr))) else: log.debug("%i %i installing flow for %s => %s out port %i" % (dpid, inport, packet.next.srcip, dstaddr, prt)) msg = of.ofp_flow_mod(command = of.OFPFC_ADD) msg.match.dl_type = 0x0800 #ipv4 msg msg.match.in_port = inport msg.match.nw_dst = "10.0.0.128/255.255.255.128" msg.actions.append(of.ofp_action_nw_addr.set_dst(dstaddr)) msg.actions.append(of.ofp_action_output(port = prt)) msg.actions.append(of.ofp_action_dl_addr.set_dst(mac)) event.connection.send(msg) log.info("ICMP echo request flow entry for %s to internal host has been instaled", packet.next.srcip) else: log.warning("Uninvolved icmp msg type") return elif self.arp_for_unknowns: # We don't know this destination. # First, we track this buffer so that we can try to resend it later # if we learn the destination, second we ARP for the destination, # which should ultimately result in it responding and us learning # where it is # Add to tracked buffers if (dpid,dstaddr) not in self.lost_buffers: self.lost_buffers[(dpid,dstaddr)] = [] bucket = self.lost_buffers[(dpid,dstaddr)] entry = (time.time() + MAX_BUFFER_TIME,event.ofp.buffer_id,inport) bucket.append(entry) while len(bucket) > MAX_BUFFERED_PER_IP: del bucket[0] # Expire things from our outstanding ARP list... self.outstanding_arps = {k:v for k,v in self.outstanding_arps.iteritems() if v > time.time()} # Check if we've already ARPed recently if (dpid,dstaddr) in self.outstanding_arps: # Oop, we've already done this one recently. return # And ARP... self.outstanding_arps[(dpid,dstaddr)] = time.time() + 4 r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.hwlen = 6 r.protolen = r.protolen r.opcode = r.REQUEST r.hwdst = ETHER_BROADCAST if dstaddr in self.vipList: r.protodst = IPAddr(REAL_IP_OF_INTERNAL_HOST) else: r.protodst = dstaddr r.hwsrc = packet.src r.protosrc = packet.next.srcip e = ethernet(type=ethernet.ARP_TYPE, src=packet.src, dst=ETHER_BROADCAST) e.set_payload(r) log.debug("%i %i ARPing for %s on behalf of %s for Ipv4" % (dpid, inport, str(r.protodst), str(r.protosrc))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD)) msg.in_port = inport event.connection.send(msg) elif isinstance(packet.next, arp): a = packet.next if a.protosrc in self.arpTable[dpid]: if self.arpTable[dpid][a.protosrc] != (inport, packet.src): log.info("%i %i RE-learned %s", dpid,inport,str(a.protosrc)) else: log.debug("%i %i learned %s", dpid,inport,str(a.protosrc)) self.arpTable[dpid][a.protosrc] = Entry(inport, packet.src) if a.protodst in self.vipList: self.srcip_dstvip_map[a.protosrc] = str(a.protodst) a.protodst = REAL_IP_OF_INTERNAL_HOST log.info("%i %i ARP %s %s => %s", dpid, inport, {arp.REQUEST:"request",arp.REPLY:"reply"}.get(a.opcode, 'op:%i' % (a.opcode,)), str(a.protosrc), str(a.protodst)) if a.prototype == arp.PROTO_TYPE_IP: if a.hwtype == arp.HW_TYPE_ETHERNET: if a.protosrc != 0: # Learn or update port/MAC info if a.protosrc in self.arpTable[dpid]: if self.arpTable[dpid][a.protosrc] != (inport, packet.src): log.info("%i %i RE-learned %s", dpid,inport,str(a.protosrc)) else: log.debug("%i %i learned %s", dpid,inport,str(a.protosrc)) self.arpTable[dpid][a.protosrc] = Entry(inport, packet.src) # Send any waiting packets... self._send_lost_buffers(dpid, a.protosrc, packet.src, inport) if a.opcode == arp.REPLY: r = arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = arp.REPLY r.hwsrc = a.hwsrc if a.protosrc == IPAddr(REAL_IP_OF_INTERNAL_HOST): if a.protodst in self.srcip_dstvip_map: r.protosrc = IPAddr(self.srcip_dstvip_map[a.protodst]) else: r.protosrc = a.protosrc r.protodst = a.protodst r.hwdst = self.arpTable[dpid][a.protodst].mac e = ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=a.hwdst) e.set_payload(r) log.debug("%i %i answering ARP for %s to %s" % (dpid, inport, str(r.protosrc), str(r.protodst))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = self.arpTable[dpid][a.protodst].port)) msg.in_port = inport event.connection.send(msg) return if a.opcode == arp.REQUEST: # Maybe we can answer if a.protodst in self.vipList: self.srcip_dstvip_map[a.protosrc] = str(a.protodst) a.protodst = IPAddr(REAL_IP_OF_INTERNAL_HOST) if a.protodst in self.arpTable[dpid]: # We have an answer... if not self.arpTable[dpid][a.protodst].isExpired(): # .. and it's relatively current, so we'll reply ourselves r = arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = arp.REPLY r.hwdst = a.hwsrc r.hwsrc = self.arpTable[dpid][a.protodst].mac r.protodst = a.protosrc if a.protodst == IPAddr(REAL_IP_OF_INTERNAL_HOST): r.protosrc = IPAddr(self.srcip_dstvip_map[a.protosrc]) else: r.protosrc = a.protodst e = ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=a.hwsrc) e.set_payload(r) log.debug("%i %i answering ARP for %s" % (dpid, inport, str(r.protosrc))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) return # Didn't know how to answer or otherwise handle this ARP, so just flood it log.debug("%i %i flooding ARP %s %s => %s" % (dpid, inport, {arp.REQUEST:"request",arp.REPLY:"reply"}.get(a.opcode, 'op:%i' % (a.opcode,)), str(a.protosrc), str(a.protodst))) r1 = arp() r1.hwtype = a.HW_TYPE_ETHERNET r1.prototype = a.PROTO_TYPE_IP r1.hwlen = 6 r1.protolen = a.protolen r1.opcode = arp.REQUEST r1.hwdst = ETHER_BROADCAST r1.protodst = IPAddr(a.protodst) r1.hwsrc = a.hwsrc r1.protosrc = a.protosrc e1 = ethernet(type=ethernet.ARP_TYPE, src=a.hwsrc, dst=ETHER_BROADCAST) e1.set_payload(r1) log.debug("%i %i ARPing for %s on behalf of %s" % (dpid, inport, str(r1.protodst), str(r1.protosrc))) msg1 = of.ofp_packet_out() msg1.data = e1.pack() msg1.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD)) msg1.in_port = inport event.connection.send(msg1)
def _handle_PacketIn (self, event): """ Handles packet in messages from the switch. """ packet = event.parsed # This is the parsed packet data. if not packet.parsed: log.warning("Ignoring incomplete packet") return packet_in = event.ofp # The actual ofp_packet_in message. # Add the new MAC to mac_to_port table if str(packet.src) not in self.mac_to_port: log.debug("mac_to_port table was updated by mac: {} -> port: {}".format(packet.src, hwsrc)) self.mac_to_port[str(packet.src)] = packet_in.in_port # ARP if packet.type == ethernet.ARP_TYPE: log.debug("in _handle_PacketIn func: an ARP requeset received.") # send to it's function self.handle_ARP_requests(packet, packet_in) # Static Routing -> handle all ipv4 traffic that comes through the router # by forwarding it to the correct subnet. elif packet.type == ethernet.IP_TYPE: log.debug("in _handle_PacketIn func: an IPv4 packet received.") ppayload = packet.payload dst_ip = str(ppayload.dstip) routable, dst_network = isRoutable (dst_ip) if routable: # Check if our router's routing_table knows the dst_network # and the dst_ip is match to dst_network if self.routing_table[str(dst_network)]['interfaceAddr'] == dst_ip: if ip_packet.protocol == ipv4.ICMP_PROTOCOL: self.handle_ICMP_packets(packet, packet_in) else: # Route the packet to it's port output_port = self.routing_table[dst_network]['Port'] # ARP if host MAC Address is not present if dst_ip not in self.arp_table: # Push frame to buffer self.buffer[dst_ip] = {'IP_Packet': ppayload, 'DestinationNetwork': dst_network} # Construct ARP Packet arp_request = arp() # now set ARP structure fields arp_request.hwdst = EthAddr('00:00:00:00:00:00') RouterInterfaceAddr = self.routing_table[dst_network]['interfaceAddr'] arp_request.hwsrc = EthAddr(self.arp_table[RouterInterfaceAddr]) arp_request.protodst = IPAddr(dst_ip) arp_request.protosrc = IPAddr(self.routing_table[dst_network]['interfaceAddr']) arp_request.opcode = arp.REQUEST # make the new pavket to send newPacket = ethernet() # set it's fields newPacket.type = newPacket.ARP_TYPE newPacket.src = EthAddr(self.arp_table[RouterInterfaceAddr]) newPacket.dst = EthAddr('FF:FF:FF:FF:FF:FF') newPacket.payload = arp_request # send the packet self.resend_packet(newPacket, output_port) if dst_ip in self.arp_table: packet.src = EthAddr(self.arp_table[self.routing_table[dst_network]['interfaceAddr']]) packet.dst = EthAddr(self.arp_table[dst_ip]) self.resend_packet(packet, output_port) # message of ICMP destination unreachable else: ethernet_frame = packet ppacket = packet.payload icmp_request_packet = ppacket.payload # make an icmp packet icmp_echo_reply_packet = icmp() icmp_echo_reply_packet.code = 0 icmp_echo_reply_packet.type = 3 # (3 type number is for icmp destination unreachable) icmp_echo_reply_packet.payload = icmp_request_packet.payload # make ipv4 header ip = ipv4() # set it's fields ip.srcip = ppacket.dstip ip.dstip = ppacket.srcip ip.protocol = ipv4.ICMP_PROTOCOL ip.payload = icmp_echo_reply_packet # make the new packet to send newPacket = ethernet() # set it's fields newPacket.type = ethernet.IP_TYPE newPacket.src = ethernet_frame.dst newPacket.dst = ethernet_frame.src newPacket.payload = ip self.resend_packet(newPacket, packet_in.in_port) def isRoutable (dst_ip): """ Check if the destination ip address wanted in packet is in our routing table or not. """ for r in self.routing_table: dst_network = r if IPAddress(dst_ip) in IPNetwork(dst_network): log.debug("packet is routable!") return True, dst_network log.debug("packet is not routable!") return False, null
def _handle_PacketIn(self, event): dpid = event.connection.dpid inport = event.port packet = copy.deepcopy(event.parsed) if not packet.parsed: log.warning("%i %i ignoring unparsed packet", dpid, inport) return if dpid not in self.arpTable: # New switch -- create an empty table self.arpTable[dpid] = {} for fake in self.fakeways: self.arpTable[dpid][IPAddr(fake)] = Entry( of.OFPP_NONE, dpid_to_mac(dpid)) # store the mac, ip info of the DNS SERVER into arpTable self.arpTable[dpid][IPAddr(IP_OF_DNS_SERVER)] = Entry( 6633, EthAddr(MAC_OF_DNS_SERVER)) if packet.type == ethernet.LLDP_TYPE: # Ignore LLDP packets return p = packet.find('dns') if p is not None and p.parsed: # Get dstName of the DNS Query dstname = '' for question in p.questions: dstname = question.name log.debug("DNS Query msg from %s: asking ip address for %s", packet.next.srcip, dstname) # Learn or update port/MAC info if packet.next.srcip in self.arpTable[dpid]: if self.arpTable[dpid][packet.next.srcip] != (inport, packet.src): log.info("%i %i RE-learned %s", dpid, inport, packet.next.srcip) else: log.debug("%i %i learned %s", dpid, inport, str(packet.next.srcip)) self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src) # generate random virtual ip for internal node n = random.randint(128, 254) vip = "10.0.0." + str(n) #add the srcip and virtual destination ip pair into srcip_dstip_map self.srcip_dstvip_map[str(packet.next.srcip)] = vip # forming answer answer = dns.rr(dstname, 1, 1, 5, len(vip), IPAddr(vip)) # write dns reply msg d = dns() d.questions = p.questions d.answers.append(answer) d.authorities = [] d.additional = [] d.id = p.id d.qr = True # dns reply d.opcode = 0 # standard d.aa = False d.tc = False d.rd = False d.ra = False d.z = False d.ad = False d.cd = False d.rcode = 0 e = ethernet(type=ethernet.IP_TYPE, src=MAC_OF_DNS_SERVER, dst=str(packet.src)) ip = ipv4(srcip=IPAddr(IP_OF_DNS_SERVER)) ip.dstip = packet.next.srcip ip.protocol = ip.UDP_PROTOCOL u = udp() u.srcport = dns.SERVER_PORT # get srcport from the packet and set it to the udp's dstport m = packet.find("udp") m.parsed u.dstport = m.srcport u.payload = d ip.payload = u e.payload = ip msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_nw_addr.set_dst( packet.next.srcip)) msg.actions.append(of.ofp_action_dl_addr.set_dst(packet.src)) msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) log.debug( " DNS reply msg has been sent to %s: %s's ip address is %s" % (str(packet.next.srcip), dstname, vip)) elif isinstance(packet.next, ipv4): log.debug("IPv4 msg: %i %i IP %s => %s", dpid, inport, packet.next.srcip, packet.next.dstip) # Send any waiting packets... self._send_lost_buffers(dpid, packet.next.srcip, packet.src, inport) print "Have sent lost buffers" # Learn or update port/MAC info if packet.next.srcip in self.arpTable[dpid]: if self.arpTable[dpid][packet.next.srcip] != (inport, packet.src): log.info("%i %i RE-learned %s", dpid, inport, packet.next.srcip) else: log.debug("%i %i learned %s", dpid, inport, str(packet.next.srcip)) self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src) srcaddr = packet.next.srcip dstaddr = packet.next.dstip if (dstaddr in self.vipList): self.srcip_dstvip_map[srcaddr] = dstaddr dstaddr = IPAddr(REAL_IP_OF_INTERNAL_HOST) if dstaddr in self.arpTable[dpid]: # We have info about what port to send it out on... prt = self.arpTable[dpid][dstaddr].port mac = self.arpTable[dpid][dstaddr].mac # Try to forward icmpmsg = packet.find("icmp") icmpmsg.parsed # icmp echo reply from internal host if icmpmsg.type == 0 and srcaddr == IPAddr( REAL_IP_OF_INTERNAL_HOST): log.info("ICMP echo reply msg from %s to %s", srcaddr, packet.next.dstip) if prt == inport: log.warning( "%i %i not sending packet for %s back out of the " + "input port" % (dpid, inport, str(dstaddr))) else: log.debug( "%i %i installing flow for %s => %s out port %i" % (dpid, inport, packet.next.srcip, dstaddr, prt)) # add flow entry msg = of.ofp_flow_mod(command=of.OFPFC_ADD) msg.match.dl_type = 0x0800 #ipv4 msg.match.nw_src = REAL_IP_OF_INTERNAL_HOST msg.match.nw_dst = dstaddr # change the srcip to virtual ip msg.actions.append( of.ofp_action_nw_addr.set_src( IPAddr(self.srcip_dstvip_map[dstaddr]))) msg.actions.append(of.ofp_action_dl_addr.set_dst(mac)) msg.actions.append(of.ofp_action_output(port=prt)) event.connection.send(msg) log.info( "ICMP echo reply flow entry for internal node to %s has been installed", packet.next.dstip) # icmp echo reply for internal host elif icmpmsg.type == 8 and dstaddr == IPAddr( REAL_IP_OF_INTERNAL_HOST): log.info("ICMP echo request msg from %s to %s", packet.next.srcip, packet.next.dstip) if prt == inport: log.warning( "%i %i not sending packet for %s back out of the " + "input port" % (dpid, inport, str(dstaddr))) else: log.debug( "%i %i installing flow for %s => %s out port %i" % (dpid, inport, packet.next.srcip, dstaddr, prt)) msg = of.ofp_flow_mod(command=of.OFPFC_ADD) msg.match.dl_type = 0x0800 #ipv4 msg msg.match.in_port = inport msg.match.nw_dst = "10.0.0.128/255.255.255.128" msg.actions.append(of.ofp_action_nw_addr.set_dst(dstaddr)) msg.actions.append(of.ofp_action_output(port=prt)) msg.actions.append(of.ofp_action_dl_addr.set_dst(mac)) event.connection.send(msg) log.info( "ICMP echo request flow entry for %s to internal host has been instaled", packet.next.srcip) else: log.warning("Uninvolved icmp msg type") return elif self.arp_for_unknowns: # We don't know this destination. # First, we track this buffer so that we can try to resend it later # if we learn the destination, second we ARP for the destination, # which should ultimately result in it responding and us learning # where it is # Add to tracked buffers if (dpid, dstaddr) not in self.lost_buffers: self.lost_buffers[(dpid, dstaddr)] = [] bucket = self.lost_buffers[(dpid, dstaddr)] entry = (time.time() + MAX_BUFFER_TIME, event.ofp.buffer_id, inport) bucket.append(entry) while len(bucket) > MAX_BUFFERED_PER_IP: del bucket[0] # Expire things from our outstanding ARP list... self.outstanding_arps = { k: v for k, v in self.outstanding_arps.iteritems() if v > time.time() } # Check if we've already ARPed recently if (dpid, dstaddr) in self.outstanding_arps: # Oop, we've already done this one recently. return # And ARP... self.outstanding_arps[(dpid, dstaddr)] = time.time() + 4 r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.hwlen = 6 r.protolen = r.protolen r.opcode = r.REQUEST r.hwdst = ETHER_BROADCAST if dstaddr in self.vipList: r.protodst = IPAddr(REAL_IP_OF_INTERNAL_HOST) else: r.protodst = dstaddr r.hwsrc = packet.src r.protosrc = packet.next.srcip e = ethernet(type=ethernet.ARP_TYPE, src=packet.src, dst=ETHER_BROADCAST) e.set_payload(r) log.debug("%i %i ARPing for %s on behalf of %s for Ipv4" % (dpid, inport, str(r.protodst), str(r.protosrc))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD)) msg.in_port = inport event.connection.send(msg) elif isinstance(packet.next, arp): a = packet.next if a.protosrc in self.arpTable[dpid]: if self.arpTable[dpid][a.protosrc] != (inport, packet.src): log.info("%i %i RE-learned %s", dpid, inport, str(a.protosrc)) else: log.debug("%i %i learned %s", dpid, inport, str(a.protosrc)) self.arpTable[dpid][a.protosrc] = Entry(inport, packet.src) if a.protodst in self.vipList: self.srcip_dstvip_map[a.protosrc] = str(a.protodst) a.protodst = REAL_IP_OF_INTERNAL_HOST log.info("%i %i ARP %s %s => %s", dpid, inport, { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )), str(a.protosrc), str(a.protodst)) if a.prototype == arp.PROTO_TYPE_IP: if a.hwtype == arp.HW_TYPE_ETHERNET: if a.protosrc != 0: # Learn or update port/MAC info if a.protosrc in self.arpTable[dpid]: if self.arpTable[dpid][a.protosrc] != (inport, packet.src): log.info("%i %i RE-learned %s", dpid, inport, str(a.protosrc)) else: log.debug("%i %i learned %s", dpid, inport, str(a.protosrc)) self.arpTable[dpid][a.protosrc] = Entry( inport, packet.src) # Send any waiting packets... self._send_lost_buffers(dpid, a.protosrc, packet.src, inport) if a.opcode == arp.REPLY: r = arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = arp.REPLY r.hwsrc = a.hwsrc if a.protosrc == IPAddr(REAL_IP_OF_INTERNAL_HOST): if a.protodst in self.srcip_dstvip_map: r.protosrc = IPAddr( self.srcip_dstvip_map[a.protodst]) else: r.protosrc = a.protosrc r.protodst = a.protodst r.hwdst = self.arpTable[dpid][a.protodst].mac e = ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=a.hwdst) e.set_payload(r) log.debug("%i %i answering ARP for %s to %s" % (dpid, inport, str( r.protosrc), str(r.protodst))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output( port=self.arpTable[dpid][a.protodst].port)) msg.in_port = inport event.connection.send(msg) return if a.opcode == arp.REQUEST: # Maybe we can answer if a.protodst in self.vipList: self.srcip_dstvip_map[a.protosrc] = str( a.protodst) a.protodst = IPAddr(REAL_IP_OF_INTERNAL_HOST) if a.protodst in self.arpTable[dpid]: # We have an answer... if not self.arpTable[dpid][ a.protodst].isExpired(): # .. and it's relatively current, so we'll reply ourselves r = arp() r.hwtype = a.hwtype r.prototype = a.prototype r.hwlen = a.hwlen r.protolen = a.protolen r.opcode = arp.REPLY r.hwdst = a.hwsrc r.hwsrc = self.arpTable[dpid][ a.protodst].mac r.protodst = a.protosrc if a.protodst == IPAddr( REAL_IP_OF_INTERNAL_HOST): r.protosrc = IPAddr( self.srcip_dstvip_map[a.protosrc]) else: r.protosrc = a.protodst e = ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=a.hwsrc) e.set_payload(r) log.debug("%i %i answering ARP for %s" % (dpid, inport, str(r.protosrc))) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output( port=of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) return # Didn't know how to answer or otherwise handle this ARP, so just flood it log.debug("%i %i flooding ARP %s %s => %s" % (dpid, inport, { arp.REQUEST: "request", arp.REPLY: "reply" }.get(a.opcode, 'op:%i' % (a.opcode, )), str(a.protosrc), str(a.protodst))) r1 = arp() r1.hwtype = a.HW_TYPE_ETHERNET r1.prototype = a.PROTO_TYPE_IP r1.hwlen = 6 r1.protolen = a.protolen r1.opcode = arp.REQUEST r1.hwdst = ETHER_BROADCAST r1.protodst = IPAddr(a.protodst) r1.hwsrc = a.hwsrc r1.protosrc = a.protosrc e1 = ethernet(type=ethernet.ARP_TYPE, src=a.hwsrc, dst=ETHER_BROADCAST) e1.set_payload(r1) log.debug("%i %i ARPing for %s on behalf of %s" % (dpid, inport, str( r1.protodst), str(r1.protosrc))) msg1 = of.ofp_packet_out() msg1.data = e1.pack() msg1.actions.append( of.ofp_action_output(port=of.OFPP_FLOOD)) msg1.in_port = inport event.connection.send(msg1)
def _routing_propagation(self): for dpid in self.dpid_table.keys(): connected_host = self.dpid_table[dpid].connected_host table1 = self.dpid_table[dpid].route_table1 table2 = self.dpid_table[dpid].route_table2 # cull route_table 2 lists into just one entry with best etx for ip in table2.keys(): ele = table2[ip][ 0] # there's always at least one entry for an IP for e in table2[ip]: if e.ip == connected_host.ip: continue e.etx += NUM_HELLO_TRANSMISSIONS / e.received_count if e.etx < ele.etx: ele = e table2[ip] = ele # make routing table 1 = routing table 2 self.dpid_table[dpid].route_table1 = self.dpid_table[ dpid].route_table2 e = [self.dpid_table[dpid].connected_host] self.dpid_table[dpid].route_table2 = { self.dpid_table[dpid].connected_host.ip: e } # send the new routing table to the connected host for dpid in self.dpid_table.keys(): # construct payload of IP to mac pairs as a json string # ie. '{"192.168.1.200" : "AA:AA:AA:AA:AA:AF", "..."}' payload = '{' for ip in self.dpid_table[dpid].route_table1.keys(): # if it's the host IP, ARP will crash, so skip it if ip == self.dpid_table[dpid].connected_host.ip: continue mac = self.dpid_table[dpid].route_table1[ip].mac pair = '"%s" : "%s", ' % (ip.toStr(), mac.toStr()) payload = payload + pair # to catch the case where only the host address is known if len(payload) > 1: payload = payload[:-2] payload = payload + '}' # pox-dev.noxrepo.narkive.com/H9Ef9T3S/errors-when-sending-new-created-packets udp_packet = udp() udp_packet.srcport = 10000 udp_packet.dstport = 10001 udp_packet.payload = payload udp_packet.len = udp.MIN_LEN + len(payload) udp_packet.set_payload(payload) ipv4_packet = ipv4() ipv4_packet.iplen = ipv4.MIN_LEN + udp_packet.len ipv4_packet.protocol = ipv4.UDP_PROTOCOL ipv4_packet.dstip = self.dpid_table[dpid].connected_host.ip ipv4_packet.srcip = IPAddr('192.168.1.254') ipv4_packet.set_payload(udp_packet) eth_packet = ethernet() eth_packet.set_payload(ipv4_packet) eth_packet.dst = self.dpid_table[dpid].connected_host.mac eth_packet.src = EthAddr('FF:FF:FF:FF:FF:FE') eth_packet.type = ethernet.IP_TYPE msg = of.ofp_packet_out(data=eth_packet) msg.actions.append( of.ofp_action_output( port=self.dpid_table[dpid].connected_host.port)) self.dpid_table[dpid].connection.send(msg) # flood the new routing table to any connected switches for dpid in self.dpid_table.keys(): # construct payload of ip, mac, etx, internet tuples as json list of dicts # ie. '[{"ip" : "192.168.1.200", "mac": "AA:AA:AA:AA:AA:AF", "etx" : "1", "internet" : "no"}, {...}]' payload = '[' ports = "" for ip in self.dpid_table[dpid].route_table1.keys(): mac = self.dpid_table[dpid].route_table1[ip].mac etx = self.dpid_table[dpid].route_table1[ip].etx internet = self.dpid_table[dpid].route_table1[ip].internet entity = '{"ip" : "%s", "mac" : "%s", "etx" : "%f", "internet" : "%s"}, ' % ( ip.toStr(), mac.toStr(), etx, internet) payload = payload + entity port = self.dpid_table[dpid].route_table1[ip].port ports += str(port) + " " payload = payload[:-2] payload = payload + ']' payload = payload.encode('utf-8', 'ignore') log.debug("%s flooding routing message: %s" % (dpid, payload)) log.debug("%s" % ports) udp_packet = udp() udp_packet.srcport = 10002 udp_packet.dstport = 10003 udp_packet.payload = payload udp_packet.len = udp.MIN_LEN + len(payload) udp_packet.set_payload(payload) ipv4_packet = ipv4() ipv4_packet.iplen = ipv4.MIN_LEN + udp_packet.len ipv4_packet.protocol = ipv4.UDP_PROTOCOL ipv4_packet.dstip = IPAddr('192.168.1.254') ipv4_packet.srcip = IPAddr('192.168.1.255') ipv4_packet.set_payload(udp_packet) eth_packet = ethernet() eth_packet.set_payload(ipv4_packet) eth_packet.dst = EthAddr('FF:FF:FF:FF:FF:FE') eth_packet.src = EthAddr('FF:FF:FF:FF:FF:FC') eth_packet.type = ethernet.IP_TYPE msg = of.ofp_packet_out(data=eth_packet) msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD)) for _ in range(NUM_HELLO_TRANSMISSIONS): self.dpid_table[dpid].connection.send(msg)
def _handle_PacketIn(self, event): """ Handles packet in messages from the switch. """ etherFrame = event.parsed # This is the parsed packet data. if not etherFrame.parsed: log.warning("Ignoring incomplete packet") return packet_in = event.ofp # The actual ofp_packet_in message. # Add the new MAC into CAM table if str(etherFrame.src) not in self.mac_to_port: log.debug('Adding %s into CAM' % str(etherFrame.src)) self.mac_to_port[str(etherFrame.src)] = packet_in.in_port # ARP if etherFrame.type == ethernet.ARP_TYPE: log.debug('RECEIVED: EtherType -> ARP') self.ARP_Handler(etherFrame, packet_in) # IP elif etherFrame.type == ethernet.IP_TYPE: log.debug('RECEIVED: EtherType -> IP') # Extract IP Packet from Ethernet Frame ip_packet = etherFrame.payload # Routable? destination_ip = str(ip_packet.dstip) source_ip = str(ip_packet.srcip) log.debug('DESTIP of THE CURRENT PACKET: ' + destination_ip + ' FROM SRCIP ' + source_ip) routable, destination_network = self.checkRoutableDestination( destination_ip) if routable: # Destined for router if self.routing_table[str(destination_network)][ 'RouterInterface'] == destination_ip: if ip_packet.protocol == ipv4.ICMP_PROTOCOL: log.debug('ICMP ECHO -> ROUTER INTERFACE') self.ICMP_Handler(etherFrame, packet_in) elif ip_packet.protocol == 0x11: log.debug('UDP PACKET DETECTED!') udp_packet = ip_packet.payload print "\nRECEIVED UDP PACKET IN PORT NUMBER : " + str( udp_packet.dstport) if udp_packet.dstport == 9999: print "\nUDP PAYLOAD : " + str(udp_packet.payload) self.handleBandwidthRequest(udp_packet.payload) # Check if any there's any routable networks for the destination IP elif routable: # Route the packet to it's respective ports output_port = self.routing_table[destination_network][ 'Port'] # ARP if host MAC Address is not present if destination_ip not in self.arp_table: # Push frame to buffer self.buffer[destination_ip] = { 'IP_Packet': ip_packet, 'DestinationNetwork': destination_network } self.ARPResolve(destination_ip, destination_network, output_port) if destination_ip in self.arp_table: if destination_ip == "10.0.2.100": print "\n--DETECTED NEW PACKET TO APPLY QOS FLOW. PROCEEDING ...--" else: print "\n--DETECTED NEW PACKET TO APPLY NORMAL FLOW. PROCEEDING ...--" self.buffer[destination_ip] = { 'IP_Packet': ip_packet, 'DestinationNetwork': destination_network } self.push_flow_label(source_ip, destination_ip, output_port) print "\n--FLOW LABEL SUCCESSFULLY PUSHED FOR NEWLY DETECTED PACKET!--" etherFrame.src = EthAddr(self.arp_table[ self.routing_table[destination_network] ['RouterInterface']]) etherFrame.dst = EthAddr( self.arp_table[destination_ip]) self.resend_packet(etherFrame, output_port) # ICMP Destination Unreachable for non-routable networks else: #if source_ip != '0.0.0.0': log.debug('PACKET IS NOT ROUTABLE for IPdest' + str(ip_packet.dstip) + ' from IPsrc ' + str(ip_packet.srcip)) ethernet_frame = etherFrame ip_packet = etherFrame.payload icmp_request_packet = ip_packet.payload icmp_echo_reply_packet = icmp() icmp_echo_reply_packet.code = 0 icmp_echo_reply_packet.type = 3 icmp_echo_reply_packet.payload = icmp_request_packet.payload ip = ipv4() ip.srcip = ip_packet.dstip ip.dstip = ip_packet.srcip ip.protocol = ipv4.ICMP_PROTOCOL ip.payload = icmp_echo_reply_packet ether = ethernet() ether.type = ethernet.IP_TYPE ether.src = ethernet_frame.dst ether.dst = ethernet_frame.src ether.payload = ip self.resend_packet(ether, packet_in.in_port) log.debug("ICMP DESTINATION UNREACHABLE SENT") log.debug("Ignoring packet with src ip 0.0.0.0")
def _handle_PacketIn(self, event): """ Handles packet in messages from the switch. """ etherFrame = event.parsed # This is the parsed packet data. if not etherFrame.parsed: log.warning("Ignoring incomplete packet") return packet_in = event.ofp # The actual ofp_packet_in message. # Add the new MAC into CAM table if str(etherFrame.src) not in self.mac_to_port: log.debug('Adding %s into CAM' % str(etherFrame.src)) self.mac_to_port[str(etherFrame.src)] = packet_in.in_port # ARP if etherFrame.type == ethernet.ARP_TYPE: log.debug('RECEIVED: EtherType -> ARP') self.ARP_Handler(etherFrame, packet_in) # IP elif etherFrame.type == ethernet.IP_TYPE: log.debug('RECEIVED: EtherType -> IP') # Extract IP Packet from Ethernet Frame ip_packet = etherFrame.payload # Routable? destination_ip = str(ip_packet.dstip) routable = False for netaddr in self.routing_table: destination_network = netaddr if IPAddress(destination_ip) in IPNetwork(destination_network): log.debug('PACKET IS ROUTABLE!') routable = True break if routable: # Destined for router if self.routing_table[str(destination_network)][ 'RouterInterface'] == destination_ip: if ip_packet.protocol == ipv4.ICMP_PROTOCOL: log.debug('ICMP ECHO -> ROUTER INTERFACE') self.ICMP_Handler(etherFrame, packet_in) # Check if any there's any routable networks for the destination IP elif routable: # Route the packet to it's respective ports output_port = self.routing_table[destination_network][ 'Port'] # ARP if host MAC Address is not present if destination_ip not in self.arp_table: # Push frame to buffer self.buffer[destination_ip] = { 'IP_Packet': ip_packet, 'DestinationNetwork': destination_network } # Construct ARP Packet arp_request = arp() arp_request.opcode = arp.REQUEST arp_request.protosrc = IPAddr( self.routing_table[destination_network] ['RouterInterface']) arp_request.protodst = IPAddr(destination_ip) arp_request.hwsrc = EthAddr(self.arp_table[ self.routing_table[destination_network] ['RouterInterface']]) arp_request.hwdst = EthAddr('00:00:00:00:00:00') ether = ethernet() ether.type = ether.ARP_TYPE ether.src = EthAddr(self.arp_table[self.routing_table[ destination_network]['RouterInterface']]) ether.dst = EthAddr('FF:FF:FF:FF:FF:FF') ether.payload = arp_request self.resend_packet(ether, output_port) if destination_ip in self.arp_table: etherFrame.src = EthAddr(self.arp_table[ self.routing_table[destination_network] ['RouterInterface']]) etherFrame.dst = EthAddr( self.arp_table[destination_ip]) self.resend_packet(etherFrame, output_port) # ICMP Destination Unreachable for non-routable networks else: log.debug('PACKET IS NOT ROUTABLE!') ethernet_frame = etherFrame ip_packet = etherFrame.payload icmp_request_packet = ip_packet.payload icmp_echo_reply_packet = icmp() icmp_echo_reply_packet.code = 0 icmp_echo_reply_packet.type = 3 icmp_echo_reply_packet.payload = icmp_request_packet.payload ip = ipv4() ip.srcip = ip_packet.dstip ip.dstip = ip_packet.srcip ip.protocol = ipv4.ICMP_PROTOCOL ip.payload = icmp_echo_reply_packet ether = ethernet() ether.type = ethernet.IP_TYPE ether.src = ethernet_frame.dst ether.dst = ethernet_frame.src ether.payload = ip self.resend_packet(ether, packet_in.in_port) log.debug("ICMP DESTINATION UNREACHABLE SENT")
def _handle_openflow_PacketIn(self, event): dpid = event.connection.dpid inport = event.port packet = event.parsed if dpid not in self.arpTable: # We've come across a new switch self.arpTable[dpid] = {} # Add the 10.0.0.10 false address in order to pick up on DNS traffic self.arpTable[dpid][IPAddr('10.0.0.10')] = Entry( of.OFPP_NONE, dpid_to_mac(dpid)) # The two types of packets we care about are IPv4 and ARP packets, so that's all we will check for. if isinstance(packet.next, ipv4): # Check and see if the IPv4 packet is a DNS packet or not if packet.next.find('dns'): pac = packet.next.find('dns') # Loop through each of the questions, though in this assignment there should only be one for question in pac.questions: # If they are looking for the protected host, in this case h3, then resolve the DNS if question.name[:2] == 'h3': log.debug(" Received DNS request for %s", question.name) # Make a new IP address. Simple algorithm, starts at 10.0.0.11 and goes up from there each time. newIP = IPAddr('10.0.0.' + str(self.ipOffset)) self.ipOffset += 1 log.debug(" Sent bogus IP Address %s to %s", newIP, packet.next.srcip) self.ipMapping[packet.next.srcip] = newIP # Set up the reply DNS packet and send it out pac.answers.append( pac.rr(question.name, question.qtype, question.qclass, 100, str(len(newIP)), newIP)) pac.qr = True pac.ra = True udpp = udp() udpp.dstport = packet.next.find('udp').srcport udpp.srcport = packet.next.find('udp').dstport udpp.payload = pac ipp = ipv4() ipp.protocol = ipp.UDP_PROTOCOL ipp.srcip = packet.next.dstip ipp.dstip = packet.next.srcip ipp.payload = udpp e = ethernet(type=ethernet.IP_TYPE, src=packet.dst, dst=packet.src) e.payload = ipp msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output(port=of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) else: # Just a normal IPv4 packet log.debug("%i %i IP %s => %s", dpid, inport, packet.next.srcip, packet.next.dstip) storesrc = packet.next.srcip if packet.next.srcip in self.ipMapping: packet.next.dstip = self.trueIP log.debug(" Translated %s to %s", self.ipMapping[packet.next.srcip], self.trueIP) elif packet.next.dstip in self.ipMapping: log.debug(" Translated %s to %s", self.trueIP, self.ipMapping[packet.next.dstip]) packet.next.srcip = self.ipMapping[packet.next.dstip] # Empty out the buffer of pending packets self._send_buffer(dpid, packet.next.srcip, packet.src, inport) # If we haven't seen the source IP before, add it to the ARP table if packet.next.srcip not in self.arpTable[dpid]: log.debug("%i %i learned %s", dpid, inport, packet.next.srcip) self.arpTable[dpid][packet.next.srcip] = Entry( inport, packet.src) # Rather than using flows, since each packet needs to have the protected IP modified # we need to see every packet. This forwards the packet with the modified IP address. if packet.next.dstip in self.arpTable[dpid]: packet.dst = self.arpTable[dpid][packet.next.dstip].mac msg = of.ofp_packet_out() msg.actions.append( of.ofp_action_output( port=self.arpTable[dpid][packet.next.dstip].port)) msg.data = packet.pack() msg.in_port = event.port event.connection.send(msg) elif isinstance(packet.next, arp): # Got an ARP packet ap = packet.next which = { arp.REQUEST: 1, arp.REPLY: 0 }.get(ap.opcode, 'op:%i' % (ap.opcode, )) # Save the old values to have the correct mappings to internal structures. storesrc = ap.protosrc storedst = ap.protodst # See if this is a request or a reply ARP in order to swap the right IP address. if ap.opcode == arp.REQUEST: if ap.protosrc in self.ipMapping: log.debug(" Translated %s to %s", self.ipMapping[ap.protosrc], self.trueIP) ap.protodst = self.trueIP elif ap.protosrc == self.trueIP: if ap.protodst in self.ipMapping: ap.protosrc = self.ipMapping[ap.protodst] log.debug("%i %i ARP %s %s => %s", dpid, inport, { arp.REQUEST: "request", arp.REPLY: "reply" }.get(ap.opcode, 'op:%i' % (ap.opcode, )), ap.protosrc, ap.protodst) if ap.prototype == arp.PROTO_TYPE_IP: if ap.hwtype == arp.HW_TYPE_ETHERNET: if ap.protosrc != 0: # If the source is new to us, add it to the ARP table if storesrc not in self.arpTable[dpid]: log.debug("%i %i learned %s", dpid, inport, storesrc) self.arpTable[dpid][storesrc] = Entry( inport, packet.src) # Send any waiting packets self._send_buffer(dpid, ap.protosrc, packet.src, inport) if ap.opcode == arp.REQUEST: if ap.protodst in self.arpTable[dpid]: # There is a matching entry in the ARP table if not self.arpTable[dpid][ ap.protodst].isExpired(): # .. and it's relatively current, so we'll reply ourselves r = arp() r.hwtype = ap.hwtype r.prototype = ap.prototype r.hwlen = ap.hwlen r.protolen = ap.protolen r.opcode = arp.REPLY r.hwdst = ap.hwsrc r.protodst = ap.protosrc r.protosrc = storedst r.hwsrc = self.arpTable[dpid][ ap.protodst].mac e = ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=ap.hwsrc) e.set_payload(r) log.debug("%i %i answering ARP for %s" % (dpid, inport, r.protosrc)) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append( of.ofp_action_output( port=of.OFPP_IN_PORT)) msg.in_port = inport event.connection.send(msg) return # To prevent the hosts from knowing the protected IP, retransmit all ARPs from the controller if (dpid, ap.protodst) not in self.buffer: self.buffer[(dpid, ap.protodst)] = [] bucket = self.buffer[(dpid, ap.protodst)] entry = (time.time() + 5, event.ofp.buffer_id, inport) bucket.append(entry) while len(bucket) > 5: del bucket[0] # Expire things from our outstanding ARP list self.outstanding_arps = { k: v for k, v in self.outstanding_arps.iteritems() if v > time.time() } # Check if we've already ARPed recently to prevent spamming if (dpid, ap.protodst) in self.outstanding_arps: return self.outstanding_arps[(dpid, ap.protodst)] = time.time() + 4 # Send out the ARP r = arp() r.hwtype = r.HW_TYPE_ETHERNET r.prototype = r.PROTO_TYPE_IP r.hwlen = 6 r.protolen = r.protolen r.opcode = r.REQUEST r.hwdst = ETHER_BROADCAST r.protodst = ap.protodst r.hwsrc = packet.src r.protosrc = storesrc e = ethernet(type=ethernet.ARP_TYPE, src=packet.src, dst=ETHER_BROADCAST) e.set_payload(r) log.debug("%i %i ARPing for %s on behalf of %s" % (dpid, inport, r.protodst, r.protosrc)) msg = of.ofp_packet_out() msg.data = e.pack() msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD)) msg.in_port = inport event.connection.send(msg)
def _handle_PacketIn(self, event): """ Handles packet in messages from the switch. """ etherFrame = event.parsed # This is the parsed packet data. if not etherFrame.parsed: log.warning("Ignoring incomplete packet") return packet_in = event.ofp # The actual ofp_packet_in message. # Add the new MAC into CAM table if str(etherFrame.src) not in self.mac_to_port: log.debug('Adding %s into CAM' % str(etherFrame.src)) self.mac_to_port[str(etherFrame.src)] = packet_in.in_port # ARP if etherFrame.type == ethernet.ARP_TYPE: log.debug('RECEIVED: EtherType -> ARP') self.ARP_Handler(etherFrame, packet_in) # IP elif etherFrame.type == ethernet.IP_TYPE: log.debug('RECEIVED: EtherType -> IP') # Extract IP Packet from Ethernet Frame ip_packet = etherFrame.payload # Routable? destination_ip = str(ip_packet.dstip) source_ip = str(ip_packet.srcip) log.debug('DESTIP of THE CURRENT PACKET: ' + destination_ip) routable = False for netaddr in self.routing_table: destination_network = netaddr if IPAddress(destination_ip) in IPNetwork(destination_network): log.debug('PACKET IS ROUTABLE!') routable = True break if routable: # Destined for router if self.routing_table[str(destination_network)][ 'RouterInterface'] == destination_ip: if ip_packet.protocol == ipv4.ICMP_PROTOCOL: log.debug('ICMP ECHO -> ROUTER INTERFACE') self.ICMP_Handler(etherFrame, packet_in) elif ip_packet.protocol == 0x11: log.debug('UDP PACKET DETECTED!') handleBandwidthRequest(ip_packet) udp_packet = ip_packet.payload print "\nRECEIVED UDP PACKET IN PORT NUMBER : " + str( udp_packet.dstport) print "\nUDP PAYLOAD : " + str(udp_packet.payload) # Check if any there's any routable networks for the destination IP elif routable: # Route the packet to it's respective ports output_port = self.routing_table[destination_network][ 'Port'] # ARP if host MAC Address is not present if destination_ip not in self.arp_table: # Push frame to buffer self.buffer[destination_ip] = { 'IP_Packet': ip_packet, 'DestinationNetwork': destination_network } # Construct ARP Packet arp_request = arp() arp_request.opcode = arp.REQUEST arp_request.protosrc = IPAddr( self.routing_table[destination_network] ['RouterInterface']) arp_request.protodst = IPAddr(destination_ip) arp_request.hwsrc = EthAddr(self.arp_table[ self.routing_table[destination_network] ['RouterInterface']]) arp_request.hwdst = EthAddr('00:00:00:00:00:00') ether = ethernet() ether.type = ether.ARP_TYPE ether.src = EthAddr(self.arp_table[self.routing_table[ destination_network]['RouterInterface']]) ether.dst = EthAddr('FF:FF:FF:FF:FF:FF') ether.payload = arp_request self.resend_packet(ether, output_port) if destination_ip in self.arp_table: if destination_ip == "10.0.4.100" and source_ip not in self.allocated_bandwidths.keys( ): print "\n--DETECTED NEW PACKET TO APPLY QOS FLOW. PROCEEDING ...--" self.buffer[destination_ip] = { 'IP_Packet': ip_packet, 'DestinationNetwork': destination_network } self.push_flow_label(source_ip, destination_ip, output_port) print "\n--QOS SUCCESSFULLY PUSHED FOR NEWLY DETECTED PACKET!--" etherFrame.src = EthAddr(self.arp_table[ self.routing_table[destination_network] ['RouterInterface']]) etherFrame.dst = EthAddr( self.arp_table[destination_ip]) self.resend_packet(etherFrame, output_port) # ICMP Destination Unreachable for non-routable networks else: log.debug('PACKET IS NOT ROUTABLE!') ethernet_frame = etherFrame ip_packet = etherFrame.payload icmp_request_packet = ip_packet.payload icmp_echo_reply_packet = icmp() icmp_echo_reply_packet.code = 0 icmp_echo_reply_packet.type = 3 icmp_echo_reply_packet.payload = icmp_request_packet.payload ip = ipv4() ip.srcip = ip_packet.dstip ip.dstip = ip_packet.srcip ip.protocol = ipv4.ICMP_PROTOCOL ip.payload = icmp_echo_reply_packet ether = ethernet() ether.type = ethernet.IP_TYPE ether.src = ethernet_frame.dst ether.dst = ethernet_frame.src ether.payload = ip self.resend_packet(ether, packet_in.in_port) log.debug("ICMP DESTINATION UNREACHABLE SENT")