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))
Example #2
0
    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)))
Example #3
0
    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)
Example #4
0
    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)
Example #5
0
  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)
Example #6
0
  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)
Example #7
0
    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)))
Example #8
0
 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)
Example #10
0
    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
Example #11
0
    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))
Example #12
0
  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
Example #13
0
  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
Example #15
0
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
Example #16
0
 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
Example #20
0
    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)
Example #22
0
  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))
Example #23
0
    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
Example #24
0
    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)
Example #25
0
    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)
Example #26
0
 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)
Example #27
0
    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
Example #28
0
	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)
Example #29
0
    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)')
Example #30
0
  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))
Example #33
0
    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:]))

    
Example #34
0
    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)
Example #38
0
  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)
Example #41
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)
            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")
Example #42
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")
Example #43
0
    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)
Example #44
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)
            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")