Example #1
0
 def sendPing (self, macEntry, ipAddr):
   """
   Builds an ETH/IP any-to-any ARP packet (an "ARP ping")
   """
   r = arp()
   r.opcode = arp.REQUEST
   r.hwdst = macEntry.macaddr
   r.hwsrc = self.ping_src_mac
   r.protodst = ipAddr
   # src is IP_ANY
   e = ethernet(type=ethernet.ARP_TYPE, src=r.hwsrc, dst=r.hwdst)
   e.payload = r
   log.debug("%i %i sending ARP REQ to %s %s",
             macEntry.dpid, macEntry.port, str(r.hwdst), str(r.protodst))
   msg = of.ofp_packet_out(data = e.pack(),
                           action = of.ofp_action_output(port=macEntry.port))
   if core.openflow.sendToDPID(macEntry.dpid, msg.pack()):
     ipEntry = macEntry.ipAddrs[ipAddr]
     ipEntry.pings.sent()
   else:
     # macEntry is stale, remove it.
     log.debug("%i %i ERROR sending ARP REQ to %s %s",
               macEntry.dpid, macEntry.port, str(r.hwdst), str(r.protodst))
     del macEntry.ipAddrs[ipAddr]
   return
  def _do_probe (self):
    """
    Send an ARP to a server to see if it's still up
    """
    self._do_expire()

    server = self.servers.pop(0)
    self.servers.append(server)

    r = arp()
    r.hwtype = r.HW_TYPE_ETHERNET
    r.prototype = r.PROTO_TYPE_IP
    r.opcode = r.REQUEST
    r.hwdst = ETHER_BROADCAST
    r.protodst = server
    r.hwsrc = self.mac
    r.protosrc = self.service_ip
    e = ethernet(type=ethernet.ARP_TYPE, src=self.mac,
                 dst=ETHER_BROADCAST)
    e.set_payload(r)
    #self.log.debug("ARPing for %s", server)
    msg = of.ofp_packet_out()
    msg.data = e.pack()
    msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
    msg.in_port = of.OFPP_NONE
    self.con.send(msg)

    self.outstanding_probes[server] = time.time() + self.arp_timeout

    core.callDelayed(self._probe_wait_time, self._do_probe)
Example #3
0
    def create_discovery_packet(self, dpid, portNum, portAddr):
        """ Create LLDP packet """

        discovery_packet = lldp()

        cid = chassis_id()
        # Maybe this should be a MAC.  But a MAC of what?  Local port, maybe?
        cid.fill(cid.SUB_LOCAL, bytes("dpid:" + hex(long(dpid))[2:-1]))
        discovery_packet.add_tlv(cid)

        pid = port_id()
        pid.fill(pid.SUB_PORT, str(portNum))
        discovery_packet.add_tlv(pid)

        ttlv = ttl()
        ttlv.fill(LLDP_TTL)
        discovery_packet.add_tlv(ttlv)

        sysdesc = system_description()
        sysdesc.fill(bytes("dpid:" + hex(long(dpid))[2:-1]))
        discovery_packet.add_tlv(sysdesc)

        discovery_packet.add_tlv(end_tlv())

        eth = ethernet()
        eth.src = portAddr
        eth.dst = NDP_MULTICAST
        eth.set_payload(discovery_packet)
        eth.type = ethernet.LLDP_TYPE

        po = of.ofp_packet_out(action=of.ofp_action_output(port=portNum), data=eth.pack())
        return po.pack()
Example #4
0
        def _handle_PacketIn(self,event):

                eth_packetRecv = event.parsed
                if eth_packetRecv.type == ethernet.ARP_TYPE: #checking if the payload is ARP pkt
                        msg = of.ofp_packet_out()
                        msg.in_port = event.port
                        arpreq = eth_packetRecv.payload # extract arp packet - arpreq
#                       log.debug('%s arp table',ARPTable)
                        if arpreq.protosrc not in ARPTable.keys(): #if no srcip entry in ARP table,add a new entry for scrip, srcmac
                                ARPTable[arpreq.protosrc] = arpreq.hwsrc
#                               print "in 1"
                        if arpreq.protodst not in ARPTable.keys():#if no entry in the ARPtable , then flood the ARP packet as l2 bc
                                eth_packetSent = eth_packetRecv
                                msg.data = eth_packetSent.pack()
                                msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD)) #flooding on all ports of the swtch

                        elif arpreq.protodst in ARPTable.keys(): # if dstip in ARPTable,build appropriate ARP reply
                                arpreply = self.buildReply(arpreq)#building the arp reply ,
                                eth_packetSent = ethernet(type = ethernet.ARP_TYPE,dst = arpreply.hwdst )#setting type of ethernet packet and src and dst mac addresses
                                eth_packetSent.set_payload(arpreply) # the payload of the eth packet is the arp packet
                                msg.data = eth_packetSent.pack()
                                msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
                                msg.in_port = event.port

                elif eth_packetRecv.type != ethernet.ARP_TYPE:
#                       print "in switching..."
                        msg = self.processPacket(event)
        #       log.debug('mac addr table %s',self.macaddrtable)
                event.connection.send(msg)
    def send_arpResponse(self, arp_req, event, packet, mac):
        '''
        Send out an ARP response
        '''
        # create the arp response packet
        arp_res = arp()
        arp_res.hwtype = arp_req.hwtype
        arp_res.prototype = arp_req.prototype
        arp_res.hwlen = arp_req.hwlen
        arp_res.protolen = arp_req.protolen
        arp_res.opcode = arp.REPLY
        arp_res.hwdst = arp_req.hwsrc
        arp_res.protodst = arp_req.protosrc
        arp_res.protosrc = arp_req.protodst
        arp_res.hwsrc = mac

        # create an ethernet package that contains the arp response we created above
        e = ethernet(type=packet.type, src=mac, dst=arp_req.hwsrc)
        e.set_payload(arp_res)
        log.debug("%i %i answering ARP for %s" % (event.connection.dpid, event.port, str(arp_res.protosrc)))

        # send the ARP response
        msg = of.ofp_packet_out()
        msg.data = e.pack()
        msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
        msg.in_port = event.port
        event.connection.send(msg)
Example #6
0
 def f_arp_reply(self,arpp):
     #print "It's a arp request"
     '''
     #print 'arpp.next=',arpp.next
     #print 'arpp.protosrc=',arpp.protosrc
     #print 'arpp.protodst=',arpp.protodst
     '''
     dstIP  = arpp.protodst.toStr()
     #print 'dstIP=',dstIP
     dstMac = self.f_get_arp_mac(dstIP)  
     #print 'dstMac=', dstMac
     if dstMac != None:
         arp_reply = arp()
         arp_reply.opcode = arp.REPLY
         arp_reply.hwdst = arpp.hwsrc
         arp_reply.protodst = arpp.protosrc
         arp_reply.protosrc = arpp.protodst
         arp_reply.hwsrc = dstMac
         ether = ethernet()
         ether.type = ethernet.ARP_TYPE
         ether.src = dstMac
         ether.dst = arpp.hwsrc            
         ether.payload = arp_reply
         #send this packet to the switch
         self.f_send_arp_reply_pkt(ether,self.packet_event.port) 
         #'''
     else:
         '''Send Openflow arp flood via Openflow flood port NOT ethernet flood !!!!!!!!'''
         self.f_send_arp_openflow_flood()
Example #7
0
    def _handle_ConnectionUp(self, event): 
        # fake mac id for service ip
        self.lb_mac = EthAddr("0A:00:00:00:00:01")
        self.connection = event.connection

        # pre emptively collecting the mac and port number of server IPs
        # by sending ARP request packets
        for ip in self.serverIp:

            # constructing ARP packet
            arpPacket = arp()
            arpPacket.opcode = arpPacket.REQUEST
            arpPacket.hwsrc = self.lb_mac
            arpPacket.hwdst = ETHER_BROADCAST
            arpPacket.protosrc = self.serviceIp
            arpPacket.protodst = ip
          
            # constructing ethernet packet with ARP as payload
            e = ethernet(type = ethernet.ARP_TYPE, src = self.connection.eth_addr, dst = ETHER_BROADCAST)
            e.set_payload(arpPacket)

            # constructing openflow out message
            msg = of.ofp_packet_out()
            msg.data = e.pack()
            msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
            msg.in_port = of.OFPP_NONE

            # sending message
            self.connection.send(msg)
Example #8
0
        def arp_reply(arp_request):
            src_ip = arp_request.protosrc
            dst_ip = arp_request.protodst
            dst_mac = EthAddr(ip_mac[str(dst_ip)])

            log.info("Faking ARP Reply")
            log.info('from ' + str(dst_ip) + ' to ' + str(src_ip))

            reply = arp()
            reply.opcode = arp.REPLY
            reply.hwtype = arp_request.hwtype
            reply.prototype = arp_request.prototype
            reply.hwlen = arp_request.hwlen
            reply.protolen = arp_request.protolen
            reply.hwsrc = dst_mac
            reply.hwdst = arp_request.hwsrc    
            reply.protosrc = dst_ip
            reply.protodst = src_ip

            ether = ethernet()
            ether.type = ethernet.ARP_TYPE
            ether.dst = packet.src
            ether.src = dst_mac
            ether.set_payload(reply)

            msg = of.ofp_packet_out()
            msg.data = ether.pack()
            msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
            msg.in_port = event.port
            
            event.connection.send(msg)
 def sendPing (self, macEntry, ipAddr):
   """
   Builds an ETH/IP any-to-any ARP packet (an "ARP ping")
   """
   r = arp()
   r.opcode = arp.REQUEST
   r.hwdst = macEntry.macaddr
   r.hwsrc = self.ping_src_mac
   r.protodst = ipAddr
   # src is IP_ANY
   e = ethernet(type=ethernet.ARP_TYPE, src=r.hwsrc, dst=r.hwdst)
   e.payload = r
   
   #custom code start
   the_file.write("Time: " + time.asctime(time.localtime(time.time())) + "\n")
   the_file.write("ARP Request:\n")
   the_file.write("Src MAC:" + str(self.ping_src_mac))
   the_file.write("Dest MAC:" + str(macEntry.macaddr))
   the_file.write("Dest IP:" + str(ipAddr))
   #custom code start
   
   log.debug("%i %i sending ARP REQ to %s %s",
             macEntry.dpid, macEntry.port, str(r.hwdst), str(r.protodst))
   msg = of.ofp_packet_out(data = e.pack(),
                           action = of.ofp_action_output(port=macEntry.port))
   if core.openflow.sendToDPID(macEntry.dpid, msg.pack()):
     ipEntry = macEntry.ipAddrs[ipAddr]
     ipEntry.pings.sent()
   else:
     # macEntry is stale, remove it.
     log.debug("%i %i ERROR sending ARP REQ to %s %s",
               macEntry.dpid, macEntry.port, str(r.hwdst), str(r.protodst))
     del macEntry.ipAddrs[ipAddr]
   return
Example #10
0
 def create_eth_packet(src, dst, payload):
         ether = ethernet()
         ether.type = pkt.ethernet.ARP_TYPE
         ether.dst = dst
         ether.src = src
         ether.payload = payload
         return ether
Example #11
0
def _arp_for_real_servers ():
  for rs in [server for server in _real_servers
             if server not in _arp_table]:
    log.debug("ARPing in UpEvent for real server %s", str(rs))
    q = arp()
    q.opcode = arp.REQUEST
    q.protodst = rs

    con = None
    for con in core.openflow.connections:
      if con is not None:
        break
    else:
      log.info("can't get any connection")
      return True

    e = ethernet(type=ethernet.ARP_TYPE, dst=ETHER_BROADCAST)
    e.payload = q
    log.debug("%s ARPing in UpEvent for real server %s",
              dpid_to_str(con.dpid), str(rs))
    msg = of.ofp_packet_out()
    msg.data = e.pack()
    msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
    # FIXME assume port number starts from 1
    # There will be a problem if port 1 is the
    # only port that will join flooding (spanning_tree)
    msg.in_port = 1
    con.send(msg)

  res = False
  for server in _real_servers:
    if server not in _arp_table:
      res = True
      break
  return res
Example #12
0
	def _router_handle_arp(self, event):
		arpPacket = event.parsed.next
		ingressPort = self.getPort(event.port)
		if arpPacket.opcode == arp.REQUEST and \
				arpPacket.protodst == ingressPort.ip:
			r = arp()
			r.opcode = arp.REPLY
			r.hwdst = arpPacket.hwsrc
			r.hwsrc = ingressPort.mac
			r.protodst = arpPacket.protosrc
			r.protosrc = arpPacket.protodst
			e = ethernet(type = ethernet.ARP_TYPE,
						 src = ingressPort.mac, 
						 dst = arpPacket.hwsrc)
			e.set_payload(r)
			msg = of.ofp_packet_out()
			msg.data = e.pack()
			msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
			msg.in_port = event.port
			event.connection.send(msg)
		elif arpPacket.opcode == arp.REPLY:
			ip = IPAddr(arpPacket.protosrc)
			mac = EthAddr(arpPacket.hwsrc)
			self.arp[ip] = EthAddr(mac)
			self._tryPurgeQueue()
			self.installRouteEntry(ip, event.port, mac)
		else:
			self._drop(event)
Example #13
0
  def handle_arp (self, packet, in_port):    # function No.2

    # Get the ARP request from packet
    arp_req = packet.next

    # Create ARP reply
    arp_rep = arp()
    arp_rep.opcode = arp.REPLY
    arp_rep.hwsrc = LOAD_BALANCER_MAC    # hardware source
    arp_rep.hwdst = arp_req.hwsrc    # hardware destination
    arp_rep.protosrc = LOAD_BALANCER_IP    # software source
    arp_rep.protodst = arp_req.protosrc    # software destination

    # Create the Ethernet packet
    eth = ethernet()
    eth.type = ethernet.ARP_TYPE
    eth.dst = packet.src
    eth.src = LOAD_BALANCER_MAC
    eth.set_payload(arp_rep)

    # Send the ARP reply to client
    msg = of.ofp_packet_out()
    msg.data = eth.pack()
    msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
    msg.in_port = in_port
    self.connection.send(msg)
Example #14
0
def send_arp_reply (reply_to, mac, src_mac = None, src_ip = None):
  """
  Send an ARP reply.

  src_mac can be None to use the "DPID MAC" or True to use the port Mac.
    (or it can be an EthAddr)
  """
  # reply_to should be a PacketIn event
  arpp = reply_to.parsed.find('arp')
  mac = EthAddr(mac)
  if src_mac is None:
    #src_mac = mac # Used to be this ???
    src_mac = reply_to.connection.eth_addr
  elif src_mac is True:
    src_mac = reply_to.connection.ports[reply_to.port].hw_addr
  else:
    src_mac = EthAddr(src_mac)
  r = arp()
  r.opcode = r.REPLY
  r.hwdst = arpp.hwsrc
  r.protodst = arpp.protosrc
  r.hwsrc = EthAddr(src_mac)
  r.protosrc = IPAddr("0.0.0.0") if src_ip is None else IPAddr(src_ip)
  e = ethernet(type=ethernet.ARP_TYPE, src=src_mac, dst=r.hwdst)
  e.payload = r
  msg = of.ofp_packet_out()
  msg.data = e.pack()
  msg.actions.append(of.ofp_action_output(port = reply_to.port))
  msg.in_port = of.OFPP_NONE
  reply_to.connection.send(msg)
Example #15
0
  def reply_to_arp(self, event, match):

    dpid = event.connection.dpid
    inport = event.port
    packet = event.parsed
    
    #print "reply to ARP request", match.dl_dst
    r = arp()
    r.opcode = arp.REPLY
    r.hwdst = match.dl_src
    if (self.addr_is_gw(dpid, match.nw_dst.toStr())):
      r.protosrc = match.nw_dst
    mac_addr=self.find_mac_addr(dpid, inport)
    #print "mac_addr=", mac_addr
    r.hwsrc = addresses.EthAddr(mac_addr)
    r.protodst = match.nw_src
    e = ethernet(type=packet.ARP_TYPE, src=r.hwsrc, dst=r.hwdst)
    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
	def handleARPmessages (self, packet, event):
		in_port = event.port
		# Get the ARP request from packet
		arp_req = packet.next

		# Create ARP reply
		arp_rep = arp()
		arp_rep.opcode = arp.REPLY
		arp_rep.hwsrc = WEB_SERVER_MAC
		arp_rep.hwdst = arp_req.hwsrc
		arp_rep.protosrc = WEB_SERVER_IP
		arp_rep.protodst = arp_req.protosrc

		# Create the Ethernet packet
		eth = ethernet()
		eth.type = ethernet.ARP_TYPE
		eth.dst = packet.src
		eth.src = WEB_SERVER_MAC
		eth.set_payload(arp_rep)

		# Send the ARP reply to client
		msg = of.ofp_packet_out()
		msg.data = eth.pack()
		msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
		msg.in_port = in_port
		self.connection.send(msg)
		pass
Example #17
0
 def cheat(self,event,dpid):  
   inport = event.port
   packet = event.parsed
   a=packet.next
   print a.protodst
   if a.protodst == "10.10.1.0":
     print "pretend arp"
     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.protodst = a.protosrc
     r.protosrc = a.protodst
     r.hwsrc = EthAddr("BC:AE:C5:43:58:DC")
     e = ethernet(type=packet.type, src=r.hwsrc, dst=r.hwdst)
     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
Example #18
0
    def sendHello(self,entry):
        inf = entry[0]
        srcip = entry[1]
        port = self.intf2Port[inf]
        mac = self.port2Mac[port]

        pwospf_hello = pwospf()
        pwospf_hello.rid = self.rid
        pwospf_hello.type = pwospf.TYPE_HELLO
        pwospf_hello.helloint = self.helloint << 16
        pwospf_hello.netmask = IPAddr("255.255.255.0").toUnsigned()

        ipp = pkt.ipv4()
        ipp.protocol = ipv4.PWOSPF_PROTOCOL
        ipp.srcip = IPAddr(srcip)
        ipp.dstip = IPAddr(ALLSPFRouters)
        ipp.payload = pwospf_hello

        ether = ethernet()
        ether.type = ethernet.IP_TYPE
        ether.src = mac

        ether.dst = ETHER_BROADCAST
        ether.payload = ipp

        msg = of.ofp_packet_out()
        msg.actions.append(of.ofp_action_output(port = port))
        msg.data = ether.pack()
        self.connection.send(msg)
Example #19
0
	def arpReply(self, packet, event, additive = 0):
		if packet.payload.opcode == arp.REQUEST:
			arp_reply = arp()
			if additive == 0:
				arp_reply.hwsrc = EthAddr('fa-31-11-11-11-11')
			elif additive == 1:
				arp_reply.hwsrc = EthAddr('fa-31-11-11-11-12')
			arp_reply.hwdst = packet.src
			arp_reply.opcode = arp.REPLY
			arp_reply.protosrc = packet.payload.protodst
			arp_reply.protodst = packet.payload.protosrc
			ether = ethernet()
			ether.type = ethernet.ARP_TYPE
			ether.dst = packet.src
			ether.src = arp_reply.hwsrc
			ether.payload = arp_reply
			#send this packet to the switch
			#see section below on this topic

			msg = of.ofp_packet_out(in_port=event.port)
			msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
			msg.data = ether
			self.connection.send(msg)

			log.debug('Replying ARP request for %s.', str(arp_reply.protosrc))
Example #20
0
    def send_arp_request(self, event, route, packet, match, nextHopIp):

        if nextHopIp in self.outstandingarp and time.time() > self.outstandingarp[nextHopIp] + self.ARP_TIMEOUT:
            return
        self.outstandingarp[nextHopIp] = time.time()
        r = pkt.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 = nextHopIp
        r.hwsrc = self.port2Mac[self.intf2Port[route.intf]]
        r.protosrc = IPAddr(ROUTERS_IPS[route.intf])

        #r.protodst = packet.next.dstip
        e = ethernet(type=ethernet.ARP_TYPE, src=r.hwsrc,
                     dst=r.hwdst)
        e.set_payload(r)
        log.debug("%s ARPing for %s on behalf of %s" % (route.intf, 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.actions.append(of.ofp_action_output(port = self.intf2Port[route.intf]))
        msg.in_port = event.port
        event.connection.send(msg)
Example #21
0
    def sendLSU(self,seq,srcip,dstip):
        print "Sending LSU Packets: ",self.name
        pwospf_hello = pwospf()
        pwospf_hello.rid = self.rid
        pwospf_hello.type = pwospf.TYPE_LSU
        pwospf_hello.seq = seq
        pwospf_hello.nadv = len(self.adjList[self.rid].items())

        for ne in self.adjList[self.rid].items():
            print ne.subnet
            pwospf_hello.advList.append(IPAddr(ne.subnet).toUnsigned())
            pwospf_hello.advList.append(IPAddr(ne.netmask).toUnsigned())
            pwospf_hello.advList.append(ne.rid)

        ipp = pkt.ipv4()
        ipp.protocol = ipv4.PWOSPF_PROTOCOL
        ipp.srcip = IPAddr(srcip)
        ipp.dstip = IPAddr(dstip)
        ipp.payload = pwospf_hello

        ether = ethernet()
        ether.type = ethernet.IP_TYPE
        ether.payload = ipp

        self.send_ipv4_packet(ether)
 def _handle_ConnectionUp(self, event): #new switch connection
     self.lb_mac = EthAddr("0A:00:00:00:00:01") #fake mac of load balancer
     self.connection = event.connection
     #write your code here!!!
     ##Send initial ARP request to the servers
     for i in self.server_ips:
         r = arp()
         r.hwtype=1
         r.prototype=0x0800
         r.hwlen=6
         r.opcode = arp.REQUEST
         r.hwsrc = self.lb_mac
         r.protosrc=self.service_ip
         r.protodst=i
         r.hwdst = EthAddr("00:00:00:00:00:00")
        # print "APR Message:  "+ str(r)
         e = ethernet(type=0x0806,src=self.lb_mac,dst=EthAddr("FF:FF:FF:FF:FF:FF"))
         e.set_payload(r)
        # print "Ethernet Frame: "+ str(e)
         #"""
         msg = of.ofp_packet_out()
         msg.data=e.pack()
         msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD))
         msg.in_port=of.OFPP_NONE
         self.connection.send(msg)
    def sendPing(cls, macEntry, ipAddr):
        """
        send Ping msg to switch.
        """
        req = arp() # Builds an "ETH/IP any-to-any ARP packet
        req.opcode = arp.REQUEST
        req.hwdst = macEntry.macaddr
        req.protodst = ipAddr
        # src is ETHER_ANY, IP_ANY
        eth = ethernet(type=ethernet.ARP_TYPE, src=req.hwsrc, dst=req.hwdst)
        eth.set_payload(req)

        log.debug("%i %i sending ARP REQ to %s %s",
                macEntry.dpid, macEntry.port, str(req.hwdst), str(req.protodst))

        msg = of.ofp_packet_out(data = eth.pack(),
                               action = of.ofp_action_output(port = macEntry.port))
        if core.openflow.sendToDPID(macEntry.dpid, msg.pack()):
            ipEntry = macEntry.ipAddrs[ipAddr]
            ipEntry.pings.sent()
        else:
            # macEntry is stale, remove it.
            log.debug("%i %i ERROR sending ARP REQ to %s %s", macEntry.dpid, macEntry.port, str(req.hwdst), str(req.protodst))
            del macEntry.ipAddrs[ipAddr]

        return
    def handle_arp(self, packet, packet_in):
        self.network.lock.acquire()
        port = self.network.routers[self.connection.dpid].ports[packet_in.in_port]
        log.debug("GOT ARP packet at router {}, type: {}; in port_mac {}; from hwsrc {}; to hwdst: {};".format(self.connection.dpid, packet.payload.opcode, port.mac, str(packet.payload.hwsrc), str(packet.payload.hwdst)))
        if packet.payload.opcode == arp.REQUEST and port.ip == str(packet.payload.protodst):
            my_arp = arp()
            my_arp.opcode = arp.REPLY
            my_arp.protosrc = IPAddr(port.ip)
            my_arp.protodst = packet.payload.protosrc
            my_arp.hwdst = packet.payload.hwsrc
            my_arp.hwsrc = EthAddr(port.mac)

            my_ether = ethernet()
            my_ether.type = ethernet.ARP_TYPE
            my_ether.dst = packet.payload.hwsrc
            my_ether.src = EthAddr(port.mac)
            my_ether.payload = my_arp
            log.debug("Sending ARP REPLY at router {}, to dest_ip {}; to port {};".format(self.connection.dpid, str(packet.payload.protosrc), port.id))
            self.send_packet(None, my_ether, packet_in.in_port, of.OFPP_NONE)

        elif packet.payload.opcode is arp.REPLY and port.mac == str(packet.payload.hwdst):
            log.debug("GOT ARP REPLY at router {}; from src_mac {}; src_ip {}; input_port {}".format(self.connection.dpid, str(packet.payload.hwsrc),packet.payload.protosrc, packet_in.in_port))
            if str(packet.payload.protosrc) in self.waiting_arp_requests:
                self.arp_cache[str(packet.payload.protosrc)] = (packet.payload.hwsrc, time.time())
                self.network.lock.release()
                self.handle_ip(self.waiting_arp_requests[str(packet.payload.protosrc)][0], self.waiting_arp_requests[str(packet.payload.protosrc)][1])
                self.network.lock.acquire()
                del self.waiting_arp_requests[str(packet.payload.protosrc)]
                
        self.network.lock.release()
Example #25
0
    def sendRequestIdentity(self, macaddr_dst, port_switch_dst):
        """
        Send EAP-REQUEST-IDENTITY to host
        Use to initialize EAP-session by switch
        Start EAP-SESSION after EAPOL-START
        """
        
        macaddr_dst = checkMac(macaddr_dst)
        port_switch_dst = checkInt(port_switch_dst)
        
        #Requete EAPOL/EAP forgee
        eap_pckt = eap(code=1, type_name=1, id=1)
        eap_pckt.type = 1
        eapol_pckt= eapol(version=2, type=0)
        eapol_pckt.next = eap_pckt
        
        self.host_progress[macaddr_dst]['eap-id']=eapol_pckt.next.getID()
        switch = self.host_progress[macaddr_dst]['switch']
        
        e= ethernet(type= 0x888e,
                        src = EthAddr(switch),
                        dst = macaddr_dst)
        e.set_payload(eapol_pckt)   

        #Envoie du paquet EAPOL/EAP
        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_dst
        self.connection.send(msg)
        log.debug("envoi REQUEST IDENTITY a %s sur le port %s" %(macaddr_dst, port_switch_dst))
  def handle_arp (self, packet, in_port):
    print "ARP Packet Arrived"

    # Get the ARP request from packet
    arp_req = packet.next

    # Create ARP reply
    arp_rep = arp()
    arp_rep.opcode = arp.REPLY

    # Show the client that it's actually the "main" server
    arp_rep.hwsrc = LOAD_BALANCER_MAC
    arp_rep.hwdst = arp_req.hwsrc
    arp_rep.protosrc = LOAD_BALANCER_IP
    arp_rep.protodst = arp_req.protosrc

    # Create the Ethernet packet
    eth = ethernet()
    eth.type = ethernet.ARP_TYPE
    eth.dst = packet.src
    eth.src = LOAD_BALANCER_MAC
    eth.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 = eth.pack()
    msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
    msg.in_port = in_port
    self.connection.send(msg)
 def _process_raw_socket_read(io_worker):
   # N.B. raw sockets return exactly one ethernet frame for every read().
   data = io_worker.peek_receive_buf()
   packet = ethernet(bytes(data))
   io_worker.consume_receive_buf(len(data))
   if log.isEnabledFor(logging.DEBUG):
     log.debug("Dequeing packet %s, port %s" % (packet, port))
   switch.process_packet(packet, port.port_no)
Example #28
0
 def _send_ethernet_packet(self, packet_type, _src, _dst, payload, out_port):
     e = ethernet(type=packet_type, src=_src, dst=_dst)
     e.set_payload(payload)
     msg = of.ofp_packet_out()
     msg.data = e.pack()
     msg.actions.append(of.ofp_action_output(port = out_port))
     msg.in_port = of.OFPP_NONE
     self.connection.send(msg)
Example #29
0
  def _handle_PacketIn (self, event):
    dpid = event.connection.dpid
    inport = event.port
    packet = event.parsed

    a = packet.find('arp')
    if not a: return

    if a.prototype != arp.PROTO_TYPE_IP:
      return

    if a.hwtype != arp.HW_TYPE_ETHERNET:
      return

    if a.opcode == arp.REQUEST:
      log.debug("%s ARP request %s => %s", dpid_to_str(dpid),
                a.protosrc, a.protodst)

      if self.use_port_mac:
        src_mac = event.connection.ports[inport].hw_addr
      else:
        src_mac = event.connection.eth_addr
      ev = ARPRequest(event.connection, a, src_mac,
                      self.eat_packets, inport)
      self.raiseEvent(ev)
      if ev.reply is not None:
        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.protodst = a.protosrc
        r.protosrc = a.protodst
        r.hwsrc = EthAddr(ev.reply)
        e = ethernet(type=packet.type, src=ev.reply_from, dst=a.hwsrc)
        e.payload = r
        log.debug("%s answering ARP for %s" % (dpid_to_str(dpid),
            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 EventHalt if ev.eat_packet else None

    elif a.opcode == arp.REPLY:
      log.debug("%s ARP reply %s => %s", dpid_to_str(dpid),
                a.protosrc, a.hwsrc)

      ev = ARPReply(event.connection,a,self.eat_packets,inport)
      self.raiseEvent(ev)
      return EventHalt if ev.eat_packet else None

    return EventHalt if self.eat_packets else None
Example #30
0
	def _handle_PacketIn(self,event):
		packet = event.parsed
		Switch_Output[event.dpid][packet.src]=event.port

		if packet.find("arp"):
			arp_packet=packet.find("arp")
			IP_To_MAC[arp_packet.protosrc]=packet.src
			if arp_packet.opcode==arp.REQUEST:
				if arp_packet.protodst in IP_To_MAC:	#reply
					#construct arp reply packet
					arp_reply=arp()
					arp_reply.hwsrc=IP_To_MAC[arp_packet.protodst]
					arp_reply.hwdst=packet.src
					arp_reply.opcode=arp.REPLY
					arp_reply.protosrc=arp_packet.protodst
					arp_reply.protodst=arp_packet.protosrc
					ether=ethernet()
					ether.type=ethernet.ARP_TYPE
					ether.dst=packet.src
					ether.src=IP_To_MAC[arp_packet.protodst]
					ether.payload=arp_reply

					# send the created arp reply back to switch
					msg=of.ofp_packet_out()
					msg.data=ether.pack()
					msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT))
					msg.in_port=event.port
					event.connection.send(msg)

				elif (arp_packet.protosrc,arp_packet.protodst) not in Switch_AntiFlood[event.dpid]:	#flood
					msg=of.ofp_packet_out(data=event.data)
					msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD))
					msg.in_port=event.port
					event.connection.send(msg)
					# Switch_AntiFlood[event.dpid].append((arp_reply.protosrc,arp_packet.protodst) )


		# if packet.find('ipv4'):
		# 	ip_packet=packet.find('ipv4')
		# 	IP_To_MAC[ip_packet.dstip]=packet.dst
		# 	IP_To_MAC[ip_packet.srcip]=packet.src

		if packet.dst in Switch_Output[event.dpid]  :
			msg=of.ofp_packet_out(data=event.ofp)
			msg.actions.append(of.ofp_action_output(port=Switch_Output[event.dpid][packet.dst]))
			msg.in_port=event.port
			event.connection.send(msg)

			Install_Flow(event,packet.src,packet.dst,Switch_Output[event.dpid][packet.dst])
			Install_Flow(event,packet.dst,packet.src,Switch_Output[event.dpid][packet.src])

		print event.dpid,'packet_in:',packet
		print 'out_put:',Switch_Output
		print 'IP_MAC',IP_To_MAC
		print 'Anti',Switch_AntiFlood
		print
Example #31
0
    def _handle_openflow_PacketIn(self, event):
        dpid = event.connection.dpid
        inport = event.port
        packet = event.parsed
        global set_Timer
        global defendDDOS
        global blockPort
        timerSet = False
        global diction

        def preventing():
            global diction
            global set_Timer
            if not set_Timer:
                set_Timer = True
            #Timer(1, _timer_func(), recurring=True)

            #print"\n\n*********new packetIN************"
            if len(diction) == 0:
                print("Enpty diction ", str(event.connection.dpid),
                      str(event.port))
                diction[event.connection.dpid] = {}
                diction[event.connection.dpid][event.port] = 1
            elif event.connection.dpid not in diction:
                diction[event.connection.dpid] = {}
                diction[event.connection.dpid][event.port] = 1
                #print "ERROR"
            else:
                if event.connection.dpid in diction:
                    # temp = diction[event.connection.dpid]
                    #print(temp)
                    #print "error check " , str(diction[event.connection.dpid][event.port])
                    if event.port in diction[event.connection.dpid]:
                        temp_count = 0
                        temp_count = diction[event.connection.dpid][event.port]
                        temp_count = temp_count + 1
                        diction[event.connection.dpid][event.port] = temp_count
                        #print "printting dpid port number and its packet count: ",  str(event.connection.dpid), str(diction[event.connection.dpid]), str(diction[event.connection.dpid][event.port])
                    else:
                        diction[event.connection.dpid][event.port] = 1

            print " switch id: ", str(event.connection.dpid)
            print " port number: ", str(event.port)
            print " packet count:", str(
                diction[event.connection.dpid][event.port]), "\n"

        def _timer_func():
            global diction
            global set_Timer
            if set_Timer == True:
                #print datetime.datetime.now(),": calling timer fucntion now!!!!!"
                for k, v in diction.iteritems():
                    for i, j in v.iteritems():
                        if j >= 50:
                            print "_____________________________________________________________________________________________"
                            print "\n", datetime.datetime.now(
                            ), "** DDOS ATTACK DETECTED **"
                            print "\n", str(diction)
                            print "\n", datetime.datetime.now(
                            ), ": BLOCKED PORT NUMBER  : ", str(
                                i), " OF SWITCH ID: ", str(k)
                            print "\n_____________________________________________________________________________________________"

                            #self.dropDDOS ()
                            dpid = k
                            msg = of.ofp_packet_out(in_port=i)
                            #msg.priority=42
                            #msg.in_port = event.port
                            #po = of.ofp_packet_out(buffer_id = buffer_id, in_port = in_port)
                            core.openflow.sendToDPID(dpid, msg)

            diction = {}

        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))

        if packet.type == ethernet.LLDP_TYPE:
            # Ignore LLDP packets
            return

        if isinstance(packet.next, ipv4):
            log.debug("%i %i IP %s => %s", dpid, inport, packet.next.srcip,
                      packet.next.dstip)
            ent_obj.statcolect(event.parsed.next.dstip)
            print "\n-Entropy = ", str(ent_obj.value), ""
            if ent_obj.value < 0.5:
                preventing()
                if timerSet is not True:
                    Timer(2, _timer_func, recurring=True)
                    timerSet = False
            else:
                timerSet = False

            # Send any waiting packets...
            self._send_lost_buffers(dpid, packet.next.srcip, packet.src,
                                    inport)

            # 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)
                    if self.wide:
                        # Make sure we don't have any entries with the old info...
                        msg = of.ofp_flow_mod(command=of.OFPFC_DELETE)
                        msg.match.nw_dst = packet.next.srcip
                        msg.match.dl_type = ethernet.IP_TYPE
                        event.connection.send(msg)
            else:
                log.debug("%i %i learned %s", dpid, inport, packet.next.srcip)
            self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src)
            #nandan: getting source ip address from the packetIn
            #myPacketInSrcIP= packet.next.srcip
            #myPacketInSrcEth= packet.src
            #myPacketInDstIP= packet.next.dstip
            #myPacketInDstEth= packet.dst

            #print "switcID: "+str(dpid)+" ,Port: "+str(event.port)+" ,MAC address: "+str(myPacketInSrcEth)+" ,SrcIP: "+ str(myPacketInSrcIP)+", Dst Mac: "+str(myPacketInDstEth)+", Dst IP: "+str(myPacketInDstEth)
            # Try to forward
            dstaddr = packet.next.dstip
            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
                if prt == inport:
                    log.warning(
                        "%i %i not sending packet for %s back out of the "
                        "input port" % (dpid, inport, dstaddr))
                else:
                    log.debug(
                        "%i %i installing flow for %s => %s out port %i" %
                        (dpid, inport, packet.next.srcip, dstaddr, prt))

                    actions = []
                    actions.append(of.ofp_action_dl_addr.set_dst(mac))
                    actions.append(of.ofp_action_output(port=prt))
                    if self.wide:
                        match = of.ofp_match(dl_type=packet.type,
                                             nw_dst=dstaddr)
                    else:
                        match = of.ofp_match.from_packet(packet, inport)

                    msg = of.ofp_flow_mod(command=of.OFPFC_ADD,
                                          idle_timeout=FLOW_IDLE_TIMEOUT,
                                          hard_timeout=of.OFP_FLOW_PERMANENT,
                                          buffer_id=event.ofp.buffer_id,
                                          actions=actions,
                                          match=match)
                    event.connection.send(msg.pack())
            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
                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" %
                          (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)

        elif isinstance(packet.next, arp):
            a = packet.next
            log.debug("%i %i ARP %s %s => %s", dpid, inport, {
                arp.REQUEST: "request",
                arp.REPLY: "reply"
            }.get(a.opcode, 'op:%i' % (a.opcode, )), a.protosrc, 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,
                                         a.protosrc)
                                if self.wide:
                                    # Make sure we don't have any entries with the old info...
                                    msg = of.ofp_flow_mod(
                                        command=of.OFPFC_DELETE)
                                    msg.match.dl_type = ethernet.IP_TYPE
                                    msg.match.nw_dst = a.protosrc
                                    event.connection.send(msg)
                        else:
                            log.debug("%i %i learned %s", dpid, inport,
                                      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.REQUEST:
                            # Maybe we can answer

                            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.protodst = a.protosrc
                                    r.protosrc = a.protodst
                                    r.hwsrc = self.arpTable[dpid][
                                        a.protodst].mac
                                    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, 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, )), a.protosrc, a.protodst))

            msg = of.ofp_packet_out(
                in_port=inport,
                data=event.ofp,
                action=of.ofp_action_output(port=of.OFPP_FLOOD))
            event.connection.send(msg)
Example #32
0
    def handle_arp(self, event):
        packet = event.parsed
        if packet.payload.opcode == arp.REQUEST:
            print "Received ARP Request (for, from, at) ", packet.payload.protodst, packet.payload.protosrc, event.dpid

            if str(packet.payload.protosrc)[-1:] == '1':
                if self.ip != packet.payload.protodst:
                    return
            # hop = self.forwardTable.findNextHop(packet.payload.protodst,event)
            # if hop is None:
            # 	return
            # if str(packet.payload.protosrc)==hop:
            # 	return

            # print "I am next hop (me,next hop from me)",self.ip,hop
            # print "REQCurrent Table", self.ipToPort
            # hop = self.forwardTable.findNextHop(packet.payload.protodst,event)
            # if hop == '':
            # 	print "Found Nothing Router",event.dpid
            # 	return

            # print "REQFound Next Hop ", hop
            # print "REQCreating Reply"
            arp_reply = arp()
            arp_reply.hwsrc = self.mac
            arp_reply.hwdst = packet.src
            arp_reply.opcode = arp.REPLY

            self.ipToPort[str(packet.payload.protosrc)] = event.port
            self.ipToMac[str(packet.payload.protosrc)] = packet.payload.hwsrc

            arp_reply.protosrc = packet.payload.protodst
            arp_reply.protodst = packet.payload.protosrc

            ether = ethernet()
            ether.type = ethernet.ARP_TYPE
            ether.dst = packet.src
            ether.src = self.mac
            ether.payload = arp_reply

            msg = of.ofp_packet_out()
            msg.data = ether.pack()
            msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT))
            msg.in_port = event.port
            event.connection.send(msg)

        elif packet.payload.opcode == arp.REPLY:
            print "Received ARP REPLY from (dest router) :", packet.payload.protosrc
            arp_reply = packet.payload

            self.ipToPort[str(arp_reply.protosrc)] = event.port
            self.ipToMac[str(arp_reply.protosrc)] = arp_reply.hwsrc
            print "Saving Mapping for (mappedIp, mappedPort, at ) :", arp_reply.protosrc, event.port, event.dpid
            print self.ipToPort
            print "Resending buffered packets ... at Router", event.dpid
            # print self.packetQueue[str(arp_reply.protosrc)]
            if str(arp_reply.protosrc) not in self.packetQueue.keys():
                return
            for pac in self.packetQueue[str(arp_reply.protosrc)]:
                print "Packet - ", str(pac.find('icmp')), arp_reply.hwsrc
                msg = of.ofp_packet_out()
                msg.actions.append(of.ofp_action_output(port=event.port))
                pac.src = self.mac
                pac.dst = arp_reply.hwsrc
                msg.data = pac.pack()
                # msg.in_port = event.port
                event.connection.send(msg)

            self.packetQueue[str(arp_reply.protosrc)] = []

        else:
            print "Some other ARP opcode, probably do something smart here"
Example #33
0
    def _handle_PacketIn(self, event):
        # Note: arp.hwsrc is not necessarily equal to ethernet.src
        # (one such example are arp replies generated by this module itself
        # as ethernet mac is set to switch dpid) so we should be careful
        # to use only arp addresses in the learning code!
        squelch = False

        dpid = event.connection.dpid
        inport = event.port
        packet = event.parsed
        if not packet.parsed:
            log.warning("%s: ignoring unparsed packet", dpid_to_str(dpid))
            return

        a = packet.find('arp')
        if not a: return

        log.debug("%s ARP %s %s => %s", dpid_to_str(dpid), {
            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:

                    if _learn:
                        # Learn or update port/MAC info
                        old_entry = _arp_table.get(a.protosrc)
                        if old_entry is None:
                            log.info("%s learned %s", dpid_to_str(dpid),
                                     a.protosrc)
                            _arp_table[a.protosrc] = Entry(a.hwsrc)
                        else:
                            if old_entry.mac is True:
                                # We never replace these special cases.
                                # Might want to warn on conflict?
                                pass
                            elif old_entry.mac != a.hwsrc:
                                if old_entry.static:
                                    log.warn(
                                        "%s static entry conflict %s: %s->%s",
                                        dpid_to_str(dpid), a.protosrc,
                                        old_entry.mac, a.hwsrc)
                                else:
                                    log.warn("%s RE-learned %s: %s->%s",
                                             dpid_to_str(dpid), a.protosrc,
                                             old_entry.mac, a.hwsrc)
                                    _arp_table[a.protosrc] = Entry(a.hwsrc)
                            else:
                                # Update timestamp
                                _arp_table[a.protosrc] = Entry(a.hwsrc)

                    if a.opcode == arp.REQUEST:
                        # Maybe we can answer

                        if a.protodst in _arp_table:
                            # We have an answer...

                            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.protodst = a.protosrc
                            r.protosrc = a.protodst
                            mac = _arp_table[a.protodst].mac
                            if mac is True:
                                # Special case -- use ourself
                                mac = event.connection.eth_addr
                            r.hwsrc = mac
                            e = ethernet(type=packet.type,
                                         src=event.connection.eth_addr,
                                         dst=a.hwsrc)
                            e.payload = r
                            if packet.type == ethernet.VLAN_TYPE:
                                v_rcv = packet.find('vlan')
                                e.payload = vlan(eth_type=e.type,
                                                 payload=e.payload,
                                                 id=v_rcv.id,
                                                 pcp=v_rcv.pcp)
                                e.type = ethernet.VLAN_TYPE
                            log.info("%s answering ARP for %s" %
                                     (dpid_to_str(dpid), 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 EventHalt if _eat_packets else None
                        else:
                            # Keep track of failed queries
                            squelch = a.protodst in _failed_queries
                            _failed_queries[a.protodst] = time.time()

        if self._check_for_flood(dpid, a):
            # Didn't know how to handle this ARP, so just flood it
            msg = "%s flooding ARP %s %s => %s" % (dpid_to_str(dpid), {
                arp.REQUEST: "request",
                arp.REPLY: "reply"
            }.get(a.opcode, 'op:%i' % (a.opcode, )), a.protosrc, a.protodst)

            if squelch:
                log.debug(msg)
            else:
                log.info(msg)

            msg = of.ofp_packet_out()
            msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD))
            msg.data = event.ofp
            event.connection.send(msg.pack())

        return EventHalt if _eat_packets else None
Example #34
0
    def _handle_PacketIn(self, event):
        """
    Packets not handled by the router rules will be
    forwarded to this method to be handled by the controller
    """

        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.

        # handle ip and arp down here
        #print "handling packet", packet
        match = of.ofp_match.from_packet(packet)
        matchip = of.ofp_match.from_packet(packet)
        if (packet.type == ethernet.IP_TYPE
            ):  #and matchip.dl_src == EthAddr("00:00:00:00:00:07")) :
            #r = ipv4()
            #r.hwsrc = EthAddr("00:00:00:00:00:07")
            #r.hwdst = EthAddr(IPREST[str(packet.payload.dstip)][0])
            #r.srcip = IPAddr(IPROUTER[str(packet.payload.dstip)])

            #r.srcip = packet.payload.srcip
            #r.dstip = packet.payload.dstip

            #packet.src = EthAddr("00:00:00:00:00:07")
            #packet.dst = EthAddr(IPREST[str(packet.payload.dstip)][0]))
            #msg = of.ofp_packet_out()
            #msg.data = packet

            #msg.actions.append(of.ofp_action_output(port = IPREST[str(packet.payload.dstip)][1]))
            #self.connection.send(packet)
            #print "mac src", EthAddr("00:00:00:00:00:07")
            #print "mac dst", EthAddr(IPREST[str(packet.payload.dstip)][0])
            #packet.payload.srcip = IPAddr(IPROUTER[str(packet.payload.srcip)])
            #print "ip src", packet.payload.srcip
            #print "ip dst", packet.payload.dstip
            e = ethernet(type=packet.IP_TYPE,
                         src=EthAddr("00:00:00:00:00:07"),
                         dst=EthAddr(IPREST[str(packet.payload.dstip)][0]))
            e.set_payload(packet.payload)
            msg = of.ofp_packet_out()
            msg.data = e.pack()
            msg.actions.append(
                of.ofp_action_output(
                    port=IPREST[str(packet.payload.dstip)][1]))
            #print "port" , IPREST[str(packet.payload.dstip)][1]
            msg.in_port = event.port
            event.connection.send(msg)

        elif (match.dl_type == packet.ARP_TYPE
              and match.nw_proto == arp.REQUEST):
            #print "generating response"
            reply = arp()
            reply.opcode = arp.REPLY
            reply.hwdst = packet.src  #match.dl_src
            #print "dl_dst", #match.dl_dst
            #print "protosrc" , packet.payload.protosrc
            #print "ip router", IPROUTER[str(packet.payload.protosrc)]
            reply.protosrc = IPAddr(IPROUTER[str(
                packet.payload.protosrc)])  #IPAddr("10.0.1.1")
            reply.protodst = packet.payload.protosrc  #match.nw_src
            reply.hwsrc = EthAddr("00:00:00:00:00:07")
            e = ethernet(type=packet.ARP_TYPE,
                         src=reply.hwsrc,
                         dst=reply.hwdst)
            e.set_payload(reply)
            msg = of.ofp_packet_out()
            msg.data = e.pack()
            #print "msg", msg
            msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT))
            #print "out port",
            msg.in_port = event.port
            event.connection.send(msg)
Example #35
0
    # Create the vlan packet = V
    vlan_packet = vlan()
    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 #36
0
    def _handle_PacketIn(self, event):
        dpid = event.connection.dpid
        inport = event.port
        packet = event.parsed
        a = packet.find('arp')
        if not a:
            return

        arp_type = {
            arp.REQUEST: "request",
            arp.REPLY: "reply"
        }.get(a.opcode, 'op:%i' % (a.opcode, ))
        log_str = "%s ARP %s %s => %s" % (dpid_to_str(dpid), arp_type,
                                          str(a.protosrc), str(a.protodst))
        if arp_type == 'reply':
            log.debug(log_str)
        else:
            log.info(log_str)

        eat = False
        dst_mac = None
        dst_dpid = None
        dst_node, dst_port = core.Outband.t.ip_and_port(a.protodst)
        if dst_node is None:
            eat = True
        else:
            dst_dpid = dst_node.dpid
        if dst_dpid is None:
            eat = True
        else:
            dst_mac = dst_port.mac
        if dst_mac is None:
            eat = True

        if (not eat) and (a.prototype == arp.PROTO_TYPE_IP):
            if a.hwtype == arp.HW_TYPE_ETHERNET:
                if a.protosrc != 0:
                    if a.opcode == arp.REQUEST:
                        # we can answer everything
                        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.protodst = a.protosrc
                        r.protosrc = a.protodst
                        #r.hwsrc = ETHER_BROADCAST
                        r.hwsrc = dst_mac
                        e = ethernet(type=ethernet.ARP_TYPE,
                                     src=self._dpid_to_mac(dpid),
                                     dst=a.hwsrc)
                        e.payload = r

                        if packet.type == ethernet.VLAN_TYPE:
                            v_rcv = packet.find('vlan')
                            e.next = vlan(eth_type=e.type,
                                          next=e.payload,
                                          id=v_rcv.id,
                                          pcp=v_rcv.pcp)
                            e.type = ethernet.VLAN_TYPE

                        log.info("%s answering ARP for %s" %
                                 (dpid_to_str(dpid), 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  # EventHalt

        # Didn't know how to handle this ARP, so just ignoring it
        msg = "%s ignoring ARP %s %s => %s" % (dpid_to_str(dpid), {
            arp.REQUEST: "request",
            arp.REPLY: "reply"
        }.get(a.opcode, 'op:%i' % (a.opcode, )), a.protosrc, a.protodst)
        log.debug(msg)

        return  # EventHalt
Example #37
0
    def _handle_PacketIn(self, event):
        """
        Handles packet in messages from the switch.
        """
        etherFrame = event.parsed
        packet_in = event.ofp

        # Incomplete frames
        if not etherFrame.parsed:
            log.warning("Ignoring incomplete packet")
            return

        # LLDP
        if etherFrame.type == ethernet.LLDP_TYPE:
            log.warning("Ignoring LLDP")
            return

        # ajouter la nouvelle adresse MAC à la table mac
        if str(etherFrame.src) not in self.mac_to_port:
            self.mac_to_port[str(etherFrame.src)] = packet_in.in_port
            log.debug('%s Adding %s into CAM' %
                      (self.dpid, str(etherFrame.src)))

        # Switchable?
        if str(etherFrame.dst) in self.mac_to_port:
            self.resend_packet(etherFrame,
                               self.mac_to_port[str(etherFrame.dst)])
            log.debug("%s Frame can be switched!" % self.dpid)

        else:
            # 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('%s RECEIVED: EtherType -> IP' % self.dpid)

                # Extract IP Packet from Ethernet Frame
                ip_packet = etherFrame.payload
                destination_ip = str(ip_packet.dstip)

                # For Router?
                if destination_ip in self.interfaces:
                    log.debug('%s ICMP ECHO -> ROUTER INTERFACE' % self.dpid)
                    self.ICMP_Handler(etherFrame, packet_in)
                else:
                    routable = False
                    for netaddr in self.routing_table.keys():
                        destination_network = netaddr
                        if IPAddress(destination_ip) in IPNetwork(
                                destination_network):
                            routable = True
                            log.debug('%s Packet can be routed!' % self.dpid)
                            break

                    local = False
                    if not routable:
                        for netaddr in self.interfaces.keys():
                            destination_network = self.interfaces[netaddr][
                                'Network']
                            if IPAddress(destination_ip) in IPNetwork(
                                    destination_network):
                                local = True
                                log.debug('%s Packet forwarded locally!' %
                                          self.dpid)
                                break

                    if local:
                        if destination_ip not in self.arp_table:
                            # ARP pour le prochain saut
                            arp_request = arp()
                            arp_request.opcode = arp.REQUEST
                            arp_request.protosrc = IPAddr(netaddr)
                            arp_request.protodst = IPAddr(destination_ip)
                            arp_request.hwsrc = EthAddr(
                                self.interfaces[netaddr]['MAC'])
                            arp_request.hwdst = EthAddr('00:00:00:00:00:00')

                            ether = ethernet()
                            ether.type = ethernet.ARP_TYPE
                            ether.src = EthAddr(
                                self.interfaces[netaddr]['MAC'])
                            ether.dst = EthAddr('FF:FF:FF:FF:FF:FF')
                            ether.payload = arp_request

                            msg = of.ofp_packet_out()
                            msg.data = ether
                            msg.actions.append(
                                of.ofp_action_output(port=of.OFPP_FLOOD))
                            self.connection.send(msg)
                        if destination_ip in self.arp_table:
                            etherFrame.src = etherFrame.dst
                            etherFrame.dst = EthAddr(
                                self.arp_table[destination_ip])
                            self.resend_packet(
                                etherFrame, self.mac_to_port[
                                    self.arp_table[destination_ip]])

                    elif routable:
                        next_hop = self.routing_table[destination_network][
                            'Next Hop']
                        if next_hop not in self.arp_table:
                            # ARP for the Next Hop
                            arp_request = arp()
                            arp_request.opcode = arp.REQUEST
                            arp_request.protosrc = IPAddr(
                                self.routing_table[destination_network]
                                ['Connected'])
                            arp_request.protodst = IPAddr(next_hop)
                            arp_request.hwsrc = EthAddr(self.interfaces[
                                self.routing_table[destination_network]
                                ['Connected']]['MAC'])
                            arp_request.hwdst = EthAddr('00:00:00:00:00:00')

                            ether = ethernet()
                            ether.type = ethernet.ARP_TYPE
                            ether.src = EthAddr(self.interfaces[
                                self.routing_table[destination_network]
                                ['Connected']]['MAC'])
                            ether.dst = EthAddr('FF:FF:FF:FF:FF:FF')
                            ether.payload = arp_request

                            msg = of.ofp_packet_out()
                            msg.data = ether
                            msg.actions.append(
                                of.ofp_action_output(port=of.OFPP_FLOOD))
                            self.connection.send(msg)
                        if next_hop in self.arp_table:
                            etherFrame.src = EthAddr(self.interfaces[
                                self.routing_table[destination_network]
                                ['Connected']]['MAC'])
                            etherFrame.dst = EthAddr(self.arp_table[next_hop])
                            self.resend_packet(
                                etherFrame,
                                self.mac_to_port[self.arp_table[next_hop]])
                            log.debug('%s Packet forwarded to next hop!' %
                                      self.dpid)
Example #38
0
    def _handle_PacketIn(self, event):
        """
    Handles packet in messages from the switch to implement above algorithm.
    """
        pkt = event.parse()
        #code.interact(local=locals())

        #log.debug("OFHandler: Got OF PacketIN!\n")

        if (event.port == 3 and pkt.type == ethernet.ARP_TYPE
                and pkt.next.opcode == arp.REQUEST):
            arp_req = pkt.next
            #log.debug("\nGot a packet request from port 3, flood it\n")
            arp_reply = arp()
            arp_reply.hwtype = arp_req.hwtype
            arp_reply.prototype = arp_req.prototype
            arp_reply.hwlen = arp_req.hwlen
            arp_reply.protolen = arp_req.protolen
            arp_reply.opcode = arp.REPLY
            arp_reply.protodst = arp_req.protosrc
            arp_reply.protosrc = arp_req.protodst
            arp_reply.hwsrc = EthAddr(self.sw_info["eth3"][1])
            arp_reply.hwdst = arp_req.hwsrc
            e = ethernet(type=pkt.type, src=arp_reply.hwsrc, dst=arp_req.hwsrc)
            e.payload = arp_reply
            msg = of.ofp_packet_out()
            msg.data = e.pack()
            msg.actions.append(of.ofp_action_output(port=of.OFPP_IN_PORT))
            msg.in_port = event.port
            event.connection.send(msg)
        elif (event.port == 3):
            #log.debug("OFHandler: raise SRPacketIn event\n")
            #log.debug("OFHandler: packet from outside, translate address\n")
            #implement an internal NAT here
            packet = event.parse()
            #print 'original packet: ', packet
            if (packet.type == ethernet.IP_TYPE):
                ip_pkt = packet.next
                #print INTERNAL_IP.keys()
                #print IP_SETTING.values()
                #print ip_pkt.dstip
                dst_ip = ip_pkt.dstip.toStr()
                src_ip = ip_pkt.srcip.toStr()
                if (dst_ip in INTERNAL_IP.keys()):
                    #print "change IP destination\n"
                    ip_pkt.dstip = IPAddr(IP_SETTING[INTERNAL_IP[dst_ip]])
                    ip_pkt.csum = ip_pkt.checksum()
                    #            ip_pkt.raw = ip_pkt.pack()
                    ip_pkt.raw = None
                    packet.next = ip_pkt
            elif (packet.type == ethernet.ARP_TYPE):
                if (packet.next.opcode == arp.REPLY):
                    arp_reply = packet.next
                    dst_ip = arp_reply.protodst.toStr()
                    if (dst_ip in INTERNAL_IP.keys()):
                        #print "change arp reply dst \n"
                        arp_reply.protodst = IPAddr(
                            IP_SETTING[INTERNAL_IP[dst_ip]])
                        #print arp_reply.protodst
                        arp_reply.raw = None
                        packet.next = arp_reply
            #print "modified packet: ", packet
            raw_packet = packet.pack()
            core.cs144_ofhandler.raiseEvent(SRPacketIn(raw_packet, event.port))
        else:
            raw_packet = pkt.raw
            core.cs144_ofhandler.raiseEvent(SRPacketIn(raw_packet, event.port))
            # Drop this packet as we won't reference it.  Just trying to be
            # safe so that OVS's/vswitchd's buffer doesn't have stale packets.
            msg = of.ofp_packet_out()
            msg.buffer_id = event.ofp.buffer_id
            msg.in_port = 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)
Example #40
0
    def _handle_PacketIn(self, event):
        dpid = event.connection.dpid
        inport = event.port
        packet = event.parsed
        if not packet.parsed:
            log.warning("DPID %i PORT %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))

        if packet.type == ethernet.LLDP_TYPE:
            # Ignore LLDP packets
            return

        if isinstance(packet.next, ipv4):
            log.debug("DPID %i PORT %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)

            # 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("DPID %i PORT %i RE-learned %s", dpid, inport,
                             packet.next.srcip)
            else:
                log.debug("DPID %i PORT %i learned %s", dpid, inport,
                          str(packet.next.srcip))
            self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src)

            if (str(packet.next.srcip) == "10.0.1.3") and (firewall == 1):
                return

            # Try to forward
            dstaddr = packet.next.dstip

            if (packet.find("icmp") and (dstaddr in switch)):
                # Reply to pings

                # Make the ping reply
                icmp = pkt.icmp()
                icmp.type = pkt.TYPE_ECHO_REPLY
                icmp.payload = packet.find("icmp").payload

                # Make the IP packet around it
                ipp = pkt.ipv4()
                ipp.protocol = ipp.ICMP_PROTOCOL
                ipp.srcip = packet.find("ipv4").dstip
                ipp.dstip = packet.find("ipv4").srcip

                # Ethernet around that...
                e = pkt.ethernet()
                e.src = packet.dst
                e.dst = packet.src
                e.type = e.IP_TYPE

                # Hook them up...
                ipp.payload = icmp
                e.payload = ipp

                # 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 = e.pack()
                msg.in_port = event.port
                event.connection.send(msg)

                log.debug("%s pinged %s", ipp.dstip, ipp.srcip)

            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
                if prt == inport:
                    log.warning(
                        "DPID %i PORT %i not sending packet for %s back out of the "
                        + "input port" % (dpid, inport, str(dstaddr)))
                else:
                    log.debug(
                        "DPID %i PORT %i installing flow for %s => %s out port %i"
                        % (dpid, inport, packet.next.srcip, dstaddr, prt))

                    actions = []
                    actions.append(of.ofp_action_dl_addr.set_dst(mac))
                    actions.append(of.ofp_action_output(port=prt))
                    match = of.ofp_match.from_packet(packet, inport)
                    match.dl_src = None  # Wildcard source MAC

                    msg = of.ofp_flow_mod(command=of.OFPFC_ADD,
                                          idle_timeout=FLOW_IDLE_TIMEOUT,
                                          hard_timeout=of.OFP_FLOW_PERMANENT,
                                          buffer_id=event.ofp.buffer_id,
                                          actions=actions,
                                          match=of.ofp_match.from_packet(
                                              packet, inport))
                    event.connection.send(msg.pack())
            elif (dstaddr not in self.arpTable[dpid]) and (dstaddr
                                                           not in switch):
                # 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()

                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 = 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("DPID %i PORT %i ARPing for %s on behalf of %s" %
                          (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)
            if (packet.find("ipv4").dstip not in node):
                icmp = pkt.icmp()
                icmp.type = pkt.TYPE_DEST_UNREACH
                icmp.code = pkt.CODE_UNREACH_HOST
                orig_ip = event.parsed.find('ipv4')

                pay = orig_ip.pack()
                pay = pay[:orig_ip.hl * 4 + 8]
                import struct
                pay = struct.pack("!HH", 0, 0) + pay
                icmp.payload = pay

                # Make the IP packet around it
                ipp = pkt.ipv4()
                ipp.protocol = ipp.ICMP_PROTOCOL
                ipp.srcip = packet.find("ipv4").dstip
                ipp.dstip = packet.find("ipv4").srcip
                # Ethernet around that...
                e = pkt.ethernet()
                e.src = packet.dst
                e.dst = packet.src
                e.type = e.IP_TYPE
                # Hook them up...
                ipp.payload = icmp
                e.payload = ipp
                # 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 = e.pack()
                msg.in_port = event.port
                event.connection.send(msg)
                log.debug("%s pinged %s", ipp.dstip, ipp.srcip)

        elif isinstance(packet.next, arp):
            a = packet.next
            log.debug("DPID %i PORT %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("DPID %i PORT %i RE-learned %s", dpid,
                                         inport, str(a.protosrc))
                        else:
                            log.debug("DPID %i PORT %i learned %s", dpid,
                                      inport, str(a.protosrc))
                        self.arpTable[dpid][a.protosrc] = Entry(
                            inport, packet.src)
                        if (str(packet.next.protosrc)
                                == "10.0.1.3") and (firewall == 1):
                            return

                        # Send any waiting packets...
                        self._send_lost_buffers(dpid, a.protosrc, packet.src,
                                                inport)

                        if a.opcode == arp.REQUEST:
                            # Maybe we can answer
                            if a.protodst != None:
                                #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.protodst = a.protosrc
                                r.protosrc = a.protodst
                                r.hwsrc = dpid_to_mac(dpid)
                                e = ethernet(type=packet.type,
                                             src=dpid_to_mac(dpid),
                                             dst=a.hwsrc)
                                e.payload = r
                                #e.set_payload(r)
                                log.debug(
                                    "DPID %i PORT %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("DPID %i PORT %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)))

            msg = of.ofp_packet_out(
                in_port=inport,
                data=event.ofp,
                action=of.ofp_action_output(port=of.OFPP_FLOOD))
            event.connection.send(msg)
Example #41
0
    def _handle_PacketIn(self, event):
        dpid = event.dpid
        inport = event.port
        packet = event.parsed

        if not packet.parsed:
            log.warning("%s: ignoring unparsed packet", dpid_to_str(dpid))
            return

        def drop(duration=None):
            """
            Drops this packet and optionally installs a flow to continue
            dropping similar ones for a while
            """
            if duration is not None:
                if not isinstance(duration, tuple):
                    duration = (duration, duration)
                msg = of.ofp_flow_mod()
                msg.match = of.ofp_match.from_packet(packet)
                msg.idle_timeout = duration[0]
                msg.hard_timeout = duration[1]
                msg.buffer_id = event.ofp.buffer_id
                event.connection.send(msg)
            elif event.ofp.buffer_id is not None:
                msg = of.ofp_packet_out()
                msg.buffer_id = event.ofp.buffer_id
                msg.in_port = event.port
                event.connection.send(msg)

        a = packet.find('arp')
        if not a:
            return

        log.debug("%s ARP %s %s => %s", dpid_to_str(dpid), {
            arp.REQUEST: "request",
            arp.REPLY: "reply"
        }.get(a.opcode, 'op:%i' % (a.opcode, )), str(a.protosrc),
                  str(a.protodst))

        if a.opcode == arp.REQUEST:

            if packet.payload.hwsrc != self.mac and packet.payload.protosrc != self.ip:

                if packet.payload.protodst in arpNat:
                    arpNat[packet.payload.protodst].append([
                        packet.payload.hwsrc, packet.payload.protosrc, dpid,
                        inport
                    ])

                else:
                    arpNat[packet.payload.protodst] = [[
                        packet.payload.hwsrc, packet.payload.protosrc, dpid,
                        inport
                    ]]

                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 = packet.payload.protodst
                r.protosrc = self.ip
                r.hwsrc = self.mac
                e = ethernet(type=ethernet.ARP_TYPE,
                             src=self.mac,
                             dst=ETHER_BROADCAST)
                e.payload = r

                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)
                return EventHalt
            else:
                return

        elif a.opcode == arp.REPLY:
            if (packet.payload.protosrc in arpNat
                    and arpNat[packet.payload.protosrc]) and (
                        packet.payload.protodst
                        == self.ip) and (packet.payload.hwdst == self.mac):

                #                 flag = False
                #                     count = 0

                #                 for e in arpNat[packet.payload.protosrc]:
                #                     if e[2] == dpid:

                #                         flag = True
                #                         i = count
                #                     count += 1

                #                 if flag:

                r = arp()
                r.hwtype = r.HW_TYPE_ETHERNET
                r.prototype = r.PROTO_TYPE_IP
                r.hwlen = 6
                r.protolen = r.protolen
                r.opcode = r.REPLY
                #                     print arpNat[packet.payload.protosrc]
                r.hwdst, r.protodst, outpid, outport = arpNat[
                    packet.payload.protosrc].pop()
                r.hwsrc = packet.payload.hwsrc
                r.protosrc = packet.payload.protosrc
                e = ethernet(type=ethernet.ARP_TYPE, src=self.mac, dst=r.hwdst)
                e.set_payload(r)
                log.debug("ARPing for %s on behalf of %s" %
                          (r.protodst, r.protosrc))
                msg = of.ofp_packet_out(
                    data=e.pack(), action=of.ofp_action_output(port=outport))
                #                     msg.data = e.pack()
                #                     msg.actions.append(of.ofp_action_output(port=outport))
                #                     msg.in_port = inport
                core.openflow.sendToDPID(outpid, msg)
                #                     event.connection.send(msg)
                #                     print "outport: "+str(outport) +" dpid:"+ str(dpid)+" outpid:"+str(outpid)
                arpttl.add(
                    (packet.payload.protosrc, packet.payload.protodst), [
                        packet.payload.hwsrc, outport, outpid, r.protodst,
                        r.hwdst
                    ])
                return EventHalt
            else:
                if (packet.payload.protosrc,
                        packet.payload.protodst) in arpttl:
                    if arpttl[(packet.payload.protosrc, packet.payload.protodst
                               )][0] == packet.payload.hwsrc:
                        print "multiple replies, but OK"
                        return EventHalt
                    else:
                        #                         if dpid == arpttl[(packet.payload.protosrc, packet.payload.protodst)][2]:
                        print "multiple replies for the same IP with different mac addresses"
                        r = arp()
                        r.hwtype = r.HW_TYPE_ETHERNET
                        r.prototype = r.PROTO_TYPE_IP
                        r.hwlen = 6
                        r.protolen = r.protolen
                        r.opcode = r.REPLY
                        r.hwdst = arpttl[(packet.payload.protosrc,
                                          packet.payload.protodst)][4]
                        r.protodst = arpttl[(packet.payload.protosrc,
                                             packet.payload.protodst)][3]
                        outport = arpttl[(packet.payload.protosrc,
                                          packet.payload.protodst)][1]
                        r.hwsrc = self.safe
                        r.protosrc = packet.payload.protosrc
                        e = ethernet(type=ethernet.ARP_TYPE,
                                     src=self.safe,
                                     dst=r.hwdst)
                        e.set_payload(r)
                        log.debug("ARPing for %s on behalf of %s" %
                                  (r.protodst, r.protosrc))
                        msg = of.ofp_packet_out(
                            data=e.pack(),
                            action=of.ofp_action_output(port=outport))
                        #                             msg = of.ofp_packet_out()
                        #                             msg.data = e.pack()
                        #                             msg.actions.append(of.ofp_action_output(port=outport))
                        #                             msg.in_port = inport
                        time.sleep(1)
                        core.openflow.sendToDPID(
                            arpttl[(packet.payload.protosrc,
                                    packet.payload.protodst)][2], msg)
                        #                             event.connection.send(msg)
                        return EventHalt
                else:
                    print "Dropping gratuitous reply"
                    return EventHalt
Example #42
0
    def _handle_openflow_PacketIn(self, event):
        dpid = event.connection.dpid
        inport = event.port
        packet = event.parsed
        log.warning("Inho #5168 : %s %s ", type(dpid), dpid)
        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))

        if packet.type == ethernet.LLDP_TYPE:
            # Ignore LLDP packets
            return

        if isinstance(packet.next, ipv4):
            log.debug("%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)

            # 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)
                    if self.wide:
                        # Make sure we don't have any entries with the old info...
                        msg = of.ofp_flow_mod(command=of.OFPFC_DELETE)
                        msg.match.nw_dst = packet.next.srcip
                        msg.match.dl_type = ethernet.IP_TYPE
                        event.connection.send(msg)
            else:
                log.debug("%i %i learned %s", dpid, inport, packet.next.srcip)
            self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src)

            # Try to forward
            dstaddr = packet.next.dstip
            if dstaddr not in self.arpTable[dpid]:
                if packet.next.srcip == IPAddr("10.0.0.1"):
                    self.arpTable[dpid][packet.next.dstip] = Entry(
                        inport, packet.src)
                    self.arpTable[dpid][packet.next.dstip].mac = EthAddr(
                        "32:d5:a3:be:19:77")
                else:
                    self.arpTable[dpid][packet.next.dstip] = Entry(
                        inport, packet.src)
                    self.arpTable[dpid][packet.next.dstip].mac = EthAddr(
                        "08:00:27:2a:87:c3")

            if packet.next.protocol == ipv4.TCP_PROTOCOL:
                if packet.next.dstip == "10.0.0.1":
                    e = pkt.ethernet()
                    e.src = EthAddr(packet.src)
                    e.dst = self.arpTable[dpid][dstaddr].mac
                    e.type = e.IP_TYPE
                    tcpp = pkt.tcp()
                    tcpp.srcport = packet.next.payload.srcport  #packet.next.payload = tcpp, packet.next = ip, packet = E
                    tcpp.dstport = packet.next.payload.dstport
                    tcpp.seq = packet.next.payload.seq
                    tcpp.ack = packet.next.payload.ack
                    tcpp.win = 29200
                    tcpp.SYN = True  #send SYN
                    tcpp.ACK = False

                    tcp = pkt.ipv4()
                    tcp.protocol = tcp.TCP_PROTOCOL
                    tcp.srcip = packet.next.srcip
                    tcp.dstip = packet.next.dstip
                    tcp.payload = tcpp

                    e.payload = tcp
                    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)

                    print(e.dst)
                    print(packet.next.dstip)

            if packet.next.protocol == ipv4.ICMP_PROTOCOL:
                e = pkt.ethernet()
                e.src = self.arpTable[dpid][dstaddr].mac
                e.dst = EthAddr(packet.src)
                e.type = e.IP_TYPE
                ipp = pkt.ipv4()
                ipp.protocol = ipp.ICMP_PROTOCOL
                ipp.srcip = packet.next.dstip
                print(ipp.srcip)
                ipp.dstip = packet.next.srcip
                icmp = pkt.icmp()
                icmp.type = pkt.ICMP.TYPE_ECHO_REPLY
                icmp.payload = packet.next.payload.payload  #copy the ping payload of the packet that they receive
                ipp.payload = icmp
                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)
                return

            if packet.next.protocol == ipv4.TCP_PROTOCOL and packet.next.dstip != "10.0.0.1":

                if packet.next.payload.SYN and not packet.next.payload.ACK:  #this is to send SYN, ACK
                    print "SYN packet", packet.next.payload

                    e = pkt.ethernet()
                    e.src = self.arpTable[dpid][dstaddr].mac
                    e.dst = EthAddr(packet.src)
                    e.type = e.IP_TYPE
                    tcpp = pkt.tcp()
                    tcpp.srcport = packet.next.payload.dstport  #packet.next.payload = tcpp, packet.next = ip, packet = E
                    tcpp.dstport = packet.next.payload.srcport
                    tcpp.seq = 0
                    tcpp.ack = packet.next.payload.seq + 1
                    tcpp.win = 29200
                    tcpp.SYN = True  #send SYN
                    tcpp.ACK = True  #send ACK

                    tcp = pkt.ipv4()
                    tcp.protocol = tcp.TCP_PROTOCOL
                    tcp.srcip = packet.next.dstip
                    tcp.dstip = packet.next.srcip
                    tcp.payload = tcpp

                    e.payload = tcp
                    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)

                    time.sleep(0.15)

                    e = pkt2.ethernet()
                    e.src = self.arpTable[dpid][dstaddr].mac
                    e.dst = EthAddr(packet.src)
                    e.type = e.IP_TYPE
                    tcpp = pkt2.tcp()
                    tcpp.srcport = packet.next.payload.dstport
                    tcpp.dstport = packet.next.payload.srcport
                    #print(packet.next.payload.ack)
                    tcpp.seq = 1
                    tcpp.ack = packet.next.payload.seq + 127
                    tcpp.win = 29200
                    tcpp.PSH = True  #send PSH
                    tcpp.ACK = True  #send ACK
                    tcpp.payload = makeMessage(
                        magic, "version",
                        makeVersionPayload(str(packet.next.dstip),
                                           str(packet.next.srcip)))

                    tcp = pkt2.ipv4()
                    tcp.protocol = tcp.TCP_PROTOCOL
                    tcp.srcip = packet.next.dstip
                    tcp.dstip = packet.next.srcip
                    tcp.payload = tcpp
                    e.payload = tcp

                    print "*****"
                    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

                # if not packet.next.payload.SYN and packet.next.payload.ACK:
                #   print "ACK packet", packet.next.payload
                #   e = pkt.ethernet()
                #   e.src = self.arpTable[dpid][dstaddr].mac
                #   e.dst = EthAddr(packet.src)
                #   e.type = e.IP_TYPE
                #   tcpp = pkt.tcp()
                #   tcpp.srcport = packet.next.payload.dstport
                #   tcpp.dstport = packet.next.payload.srcport
                #   # tcpp.seq = 1 # will be random
                #   tcpp.ack = packet.next.payload.ack+1
                #   # tcpp.SYN = True
                #   tcpp.ACK = True

                #   tcp = pkt.ipv4()
                #   tcp.protocol = tcp.TCP_PROTOCOL
                #   tcp.srcip = packet.next.dstip
                #   tcp.dstip = packet.next.srcip
                #   tcp.payload = tcpp

                #   e.payload = tcp
                #   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
                else:
                    print "Not SYN", packet.next.payload
            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
                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" %
                          (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)

        elif isinstance(packet.next, arp):
            a = packet.next
            log.debug("%i %i ARP %s %s => %s", dpid, inport, {
                arp.REQUEST: "request",
                arp.REPLY: "reply"
            }.get(a.opcode, 'op:%i' % (a.opcode, )), a.protosrc, a.protodst)

            if a.protosrc == IPAddr("10.0.0.1"):
                if a.opcode == arp.REQUEST:

                    if a.protodst not in self.arpTable[dpid]:
                        self.arpTable[dpid][a.protodst] = Entry(
                            inport, packet.src)
                        self.arpTable[dpid][a.protodst].mac = EthAddr(
                            "32:d5:a3:be:19:77")

                    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.protodst = a.protosrc
                    r.protosrc = a.protodst
                    r.hwsrc = self.arpTable[dpid][a.protodst].mac
                    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: %s" %
                              (dpid, inport, r.protosrc, r.hwsrc))
                    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, )), a.protosrc, a.protodst))

            msg = of.ofp_packet_out(
                in_port=inport,
                data=event.ofp,
                action=of.ofp_action_output(port=of.OFPP_FLOOD))
            event.connection.send(msg)
Example #43
0
    def _handle_PacketIn(self, event):
        """
    Gerencia os pacotes de entrada.
    :param event:  Evento relacionado à chamada da função.
    :return: Sem retorno.
    """
        dpid = event.connection.dpid
        inport = event.port
        packet = 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] = {}

        if packet.type == ethernet.LLDP_TYPE:
            # Ignore LLDP packets
            return

        if isinstance(packet.next, ipv4):
            log.debug("%i %i IP %s => %s", dpid, inport,
                      str(packet.next.srcip), str(packet.next.dstip))

            # 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,
                             str(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)

            # Try to forward
            dstaddr = packet.next.dstip
            if dstaddr in self.arpTable[dpid]:
                # We have info about what port to send it out on...

                prt = self.arpTable[dpid][dstaddr].port
                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, str(
                            packet.next.srcip), str(dstaddr), prt))

                    msg = of.ofp_flow_mod(
                        command=of.OFPFC_ADD,
                        idle_timeout=FLOW_IDLE_TIMEOUT,
                        hard_timeout=of.OFP_FLOW_PERMANENT,
                        buffer_id=event.ofp.buffer_id,
                        action=of.ofp_action_output(port=prt),
                        match=of.ofp_match.from_packet(packet, inport))
                    event.connection.send(msg.pack())

        elif isinstance(packet.next, arp):
            a = packet.next
            log.debug("%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)

                        if a.opcode == arp.REQUEST:
                            # Maybe we can answer

                            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.protodst = a.protosrc
                                    r.protosrc = a.protodst
                                    r.hwsrc = self.arpTable[dpid][
                                        a.protodst].mac
                                    e = ethernet(type=packet.type,
                                                 src=r.hwsrc,
                                                 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)))

            msg = of.ofp_packet_out(
                in_port=inport,
                action=of.ofp_action_output(port=of.OFPP_FLOOD))
            if event.ofp.buffer_id is of.NO_BUFFER:
                # Try sending the (probably incomplete) raw data
                msg.data = event.data
            else:
                msg.buffer_id = event.ofp.buffer_id
            event.connection.send(msg.pack())

        return
    def _handle_openflow_PacketIn(self, event):
        global packets
        global dpids

        dpid = event.connection.dpid
        inport = event.port
        packet = 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))

        if packet.type == ethernet.LLDP_TYPE:
            # Ignore LLDP packets
            return

        if isinstance(packet.next, ipv4):
            print "dpid and port: (", event.connection.dpid, event.port, ")"
            log.debug("%i %i IP %s => %s", dpid, inport, packet.next.srcip,
                      packet.next.dstip)

            # ['frame.len', 'ip.hdr_len',
            #  'ip.len', 'ip.flags.rb', 'ip.flags.df', 'p.flags.mf', 'ip.frag_offset',
            #  'ip.ttl', 'ip.proto', 'tcp.srcport', 'tcp.dstport',
            #  'tcp.len', 'tcp.ack', 'tcp.flags.res', 'tcp.flags.ns', 'tcp.flags.cwr',
            #  'tcp.flags.ecn', 'tcp.flags.urg', 'tcp.flags.ack', 'tcp.flags.push',
            #  'tcp.flags.reset', 'tcp.flags.syn', 'tcp.flags.fin', 'tcp.window_size',
            #  'tcp.time_delta']

            x_test = [
                len(packet), packet.next.hl, packet.next.iplen, 0,
                packet.next.flags == 1, packet.next.flags == 2,
                packet.next.frag, packet.next.ttl, packet.next.protocol,
                packet.next.next.srcport, packet.next.next.dstport,
                len(packet.next.next), packet.next.next.ACK, 0, 0, 0, 0, 0,
                packet.next.next.flags == 16, packet.next.next.flags == 8,
                packet.next.next.flags == 4, packet.next.next.flags == 2,
                packet.next.next.flags == 1, packet.next.next.win, 0
            ]
            defender = Detector()
            packets.append(x_test)
            dpids.append(event.connection.dpid)
            if len(packets) >= 25:
                normal = defender.predictResult(packets)
                print "value: ", normal
                if int(normal[0][0] + 0.5):
                    print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~normal~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
                    packets.pop(0)
                    dpids.pop(0)
                if not int(normal[0][0] + 0.5):
                    print '--------------- -------------------Warning!! DDoS detected! -----------------------------------------------'
                    print 'the prediction from LSTM DL model: ', normal[0][
                        0], '(1: normal, 0: attack)'
                    print 'blocking the malicious attack.......................................'
                    print 'event.connection.dpid: ', event.connection.dpid
                    print '---------------------------------------------------------------------------------------------------------'
                    for i, dpid in enumerate(dpids):
                        # print "inport, dstport: ", packets[i][9], packets[i][10]
                        msg = of.ofp_packet_out(in_port=packets[i][9] + 25)
                        core.openflow.sendToDPID(dpid, msg)
                    packets.pop(0)
                    dpids.pop(0)
                    os._exit(0)

            # Send any waiting packets...
            self._send_lost_buffers(dpid, packet.next.srcip, packet.src,
                                    inport)

            # 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)
                    if self.wide:
                        # Make sure we don't have any entries with the old info...
                        msg = of.ofp_flow_mod(command=of.OFPFC_DELETE)
                        msg.match.nw_dst = packet.next.srcip
                        msg.match.dl_type = ethernet.IP_TYPE
                        event.connection.send(msg)
            else:
                log.debug("%i %i learned %s", dpid, inport, packet.next.srcip)
            self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src)
            print "forwarding"
            # Try to forward
            dstaddr = packet.next.dstip
            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
                if prt == inport:
                    log.warning(
                        "%i %i not sending packet for %s back out of the "
                        "input port" % (dpid, inport, dstaddr))
                else:
                    log.debug(
                        "%i %i installing flow for %s => %s out port %i" %
                        (dpid, inport, packet.next.srcip, dstaddr, prt))

                    actions = []
                    actions.append(of.ofp_action_dl_addr.set_dst(mac))
                    actions.append(of.ofp_action_output(port=prt))
                    if self.wide:
                        match = of.ofp_match(dl_type=packet.type,
                                             nw_dst=dstaddr)
                    else:
                        match = of.ofp_match.from_packet(packet, inport)

                    msg = of.ofp_flow_mod(command=of.OFPFC_ADD,
                                          idle_timeout=FLOW_IDLE_TIMEOUT,
                                          hard_timeout=of.OFP_FLOW_PERMANENT,
                                          buffer_id=event.ofp.buffer_id,
                                          actions=actions,
                                          match=match)
                    event.connection.send(msg.pack())
            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
                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" %
                          (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)

        elif isinstance(packet.next, arp):
            a = packet.next
            log.debug("%i %i ARP %s %s => %s", dpid, inport, {
                arp.REQUEST: "request",
                arp.REPLY: "reply"
            }.get(a.opcode, 'op:%i' % (a.opcode, )), a.protosrc, 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,
                                         a.protosrc)
                                if self.wide:
                                    # Make sure we don't have any entries with the old info...
                                    msg = of.ofp_flow_mod(
                                        command=of.OFPFC_DELETE)
                                    msg.match.dl_type = ethernet.IP_TYPE
                                    msg.match.nw_dst = a.protosrc
                                    event.connection.send(msg)
                        else:
                            log.debug("%i %i learned %s", dpid, inport,
                                      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.REQUEST:
                            # Maybe we can answer

                            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.protodst = a.protosrc
                                    r.protosrc = a.protodst
                                    r.hwsrc = self.arpTable[dpid][
                                        a.protodst].mac
                                    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, 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, )), a.protosrc, a.protodst))

            msg = of.ofp_packet_out(
                in_port=inport,
                data=event.ofp,
                action=of.ofp_action_output(port=of.OFPP_FLOOD))
            event.connection.send(msg)
Example #45
0
    def _handle_PacketIn(self, event):
        packet = event.parsed
        if not packet.parsed:
            return

        port = event.port
        dpid = event.connection.dpid
        pnext = packet.next
        # If destination is known via other switches
        odd_ips = ["10.0.0.1", "10.0.0.3", "10.0.0.5"]
        even_ips = ["10.0.0.2", "10.0.0.4", "10.0.0.6"]

        log.info("current packet dpid: %i at port: %s  " %\
              (dpid, port))
        # A new switch has connected
        if dpid not in self._arp_table:
            self._arp_table[dpid] = {}
            log.info("Initiating ARP table for dpid: %i" % (dpid, ))
        # If it is an IPv4 packet
        if isinstance(pnext, ipv4):
            # Learn or update mac and port info for IP
            #if it is the leaf switches
            if int(dpid) in [1, 2, 3]:
                log.info("leaf dpid")
                if pnext.srcip in odd_ips:
                    log.info("odd src ip matched src ip %s" % (pnext.srcip, ))
                    self._arp_table[dpid][pnext.srcip] = (packet.src, 1)
                else:
                    self._arp_table[dpid][pnext.srcip] = (packet.src, 2)
            self._master_arp_table[pnext.srcip] = packet.src
            log.info("Updating ARP table for dpid: %i & IP: %s with (%s, %i)" %\
              (dpid, pnext.srcip, packet.src, port,))
            # Find the packet destination
            dst_ip = pnext.dstip
            # If destination is known then
            if dst_ip in self._arp_table[dpid]:
                # Obtain its mac and port
                dst_mac, dst_port = self._arp_table[dpid][dst_ip]
                log.info("Probed ARP table for dpid: %i & IP: %s to get (%s, %i)" %\
                  (dpid, dst_ip, dst_mac, dst_port,))
                # Add the flow rule to switch
                if dst_port != port:
                    message = of.ofp_flow_mod(buffer_id=event.ofp.buffer_id)
                    message.actions.append(
                        of.ofp_action_dl_addr.set_dst(dst_mac))
                    message.actions.append(of.ofp_action_output(port=dst_port))
                    message.match = of.ofp_match.from_packet(packet, port)
                    event.connection.send(message)
            else:
                ''' # If destination is known via other switches
        odd_ips  = ["10.0.0.1", "10.0.0.3", "10.0.0.5"]
        even_ips = ["10.0.0.2", "10.0.0.4", "10.0.0.6"]
        if pnext.srcip in odd_ips:
          # route throgh s4
          log.info("Odd IP: %s should be routed through S4" % (pnext.srcip,))
        elif pnext.srcip in even_ips:
          log.info("Even IP: %s should be routed through S4" % (pnext.srcip,))
        else:
          # unknown dpid
          log.info("Encountered unknown IP: %s" % (pnext.srcip,))
          '''

        # Else if it is an ARP packet
        elif isinstance(pnext, arp):
            if pnext.prototype == arp.PROTO_TYPE_IP and pnext.hwtype == arp.HW_TYPE_ETHERNET \
              and pnext.protosrc != 0:
                # Learn or update MAC & port info for IP
                self._arp_table[dpid][pnext.protosrc] = (packet.src, port)
                self._master_arp_table[pnext.protosrc] = packet.src
                log.info("Updating ARP table for dpid: %i & IP: %s with (%s, %i)" %\
                  (dpid, pnext.protosrc, packet.src, port,))
                # If it is an ARP request and we know the destination
                # if pnext.opcode == arp.REQUEST and pnext.protodst in self._arp_table[dpid]:
                if pnext.opcode == arp.REQUEST and pnext.protodst in self._master_arp_table:
                    # Send the ARP response
                    res = arp()
                    # res.hwsrc, _  = self._arp_table[dpid][pnext.protodst]
                    res.hwsrc = self._master_arp_table[pnext.protodst]
                    res.hwtype = arp.HW_TYPE_ETHERNET
                    res.hwdst = pnext.hwsrc
                    res.hwlen = pnext.hwlen
                    res.prototype = arp.PROTO_TYPE_IP
                    res.protodst = pnext.protosrc
                    res.protosrc = pnext.protodst
                    res.protolen = pnext.protolen
                    res.opcode = arp.REPLY
                    eth = ethernet()
                    eth.type = packet.type
                    eth.src = EthAddr("%012x" % (dpid & 0xFFFFFFFFFFFF))
                    eth.dst = res.hwdst
                    eth.set_payload(res)
                    message = of.ofp_packet_out()
                    message.in_port = port
                    message.data = eth.pack()
                    message.actions.append(
                        of.ofp_action_output(port=of.OFPP_IN_PORT))
                    event.connection.send(message)
                    log.info("Responded to ARP request for dpid: %s and destination: %s" %\
                      (dpid, pnext.protodst,))
Example #46
0
def _handle_PacketIn (event):

   #log.info("*** _handle_PacketIn... ***")

   dpid = event.connection.dpid

   inport = event.port

   packet = event.parsed

   if not packet.parsed:

      log.warning("%i %i ignoring unparsed packet", dpid, inport)

      return

 

   a = packet.find('arp')

   if not a: return

 

   log.info("%s ARP %s %s => %s", dpid_to_str(dpid),

      {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.opcode == arp.REQUEST:

         if str(a.protodst)=="192.168.1.1":

           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.protodst = a.protosrc

           r.protosrc = a.protodst

           r.hwsrc = EthAddr("00:00:00:00:00:03")

           e = ethernet(type=packet.type, src=r.hwsrc,

                            dst=a.hwsrc)

           e.payload = r

           log.info("%s answering ARP for %s" % (dpid_to_str(dpid),

                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)  

         if str(a.protodst)=="10.0.0.2":

           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.protodst = a.protosrc

           r.protosrc = a.protodst

           r.hwsrc = EthAddr("00:00:00:00:00:04")

           e = ethernet(type=packet.type, src=r.hwsrc,

                            dst=a.hwsrc)

           e.payload = r

           log.info("%s answering ARP for %s" % (dpid_to_str(dpid),

                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)
Example #47
0
 def parse(self):
     if self._parsed is None:
         self._parsed = ethernet(self.data)
     return self._parsed
    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("!LOG WARN! S1 : 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('!LOG! S1 : Adding %s into CAM, recv from %s' %
                      (str(etherFrame.src), str(packet_in.in_port)))
            self.mac_to_port[str(etherFrame.src)] = packet_in.in_port

        # ARP
        if etherFrame.type == ethernet.ARP_TYPE:
            log.debug('!LOG! S1 : RECEIVED: EtherType -> ARP')
            self.ARP_Handler(etherFrame, packet_in)
        # IP
        elif etherFrame.type == ethernet.IP_TYPE:
            log.debug('!LOG! S1 : 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('!LOG! S1 : 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('!LOG! S1 : 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('!LOG! S1 : 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("!LOG! S1 : ICMP DESTINATION UNREACHABLE SENT")
    def ARP_Handler(self, packet, packet_in):
        log.debug("!LOG! S1 : ARP FRAME RECEIVED FROM %s" % packet_in.in_port)

        if packet.payload.opcode == arp.REQUEST:
            log.debug("!LOG! S1 : IT'S AN ARP REQUEST!")

            arp_payload = packet.payload
            arp_request_ip = str(arp_payload.protodst)
            if arp_request_ip in self.arp_table:

                arp_reply = arp()
                arp_reply.opcode = arp.REPLY
                arp_reply.hwsrc = EthAddr(self.arp_table[arp_request_ip])
                arp_reply.hwdst = arp_payload.hwsrc
                arp_reply.protosrc = arp_payload.protodst
                arp_reply.protodst = arp_payload.protosrc

                ether = ethernet()
                ether.type = ether.ARP_TYPE
                ether.src = EthAddr(self.arp_table[arp_request_ip])
                ether.dst = arp_payload.hwsrc
                ether.payload = arp_reply

                self.resend_packet(ether, packet_in.in_port)
                log.debug("!LOG! S1 : ARP REPLY SENT!")

        elif packet.payload.opcode == arp.REPLY:
            log.debug("!LOG! S1 : IT'S AN ARP REPLY!")

            arp_payload = packet.payload
            hwsrc = str(arp_payload.hwsrc)
            srcip = str(arp_payload.protosrc)
            if srcip not in self.arp_table:
                self.arp_table[srcip] = hwsrc
                self.mac_to_port[hwsrc] = packet_in.in_port
                log.debug("!LOG! S1 : %s %s INSTALLED TO CAM TABLE" %
                          (srcip, hwsrc))

            # If there are packets in buffer waiting to be sent out
            if srcip in self.buffer.keys():
                print 'Packet waiting in buffer!'
                out_port = self.routing_table[self.buffer[srcip]
                                              ['DestinationNetwork']]['Port']
                ip_packet = self.buffer[srcip]['IP_Packet']
                etherFrame = ethernet()
                etherFrame.type = etherFrame.IP_TYPE
                etherFrame.src = EthAddr(self.arp_table[self.routing_table[
                    self.buffer[srcip]['DestinationNetwork']]
                                                        ['RouterInterface']])
                etherFrame.dst = EthAddr(self.arp_table[srcip])
                etherFrame.payload = ip_packet
                self.resend_packet(etherFrame, out_port)

                msg = of.ofp_flow_mod()
                print self.buffer[srcip]['DestinationNetwork']
                msg.priority = 10
                msg.match.dl_type = ethernet.IP_TYPE
                msg.match.nw_proto = ipv4.ICMP_PROTOCOL
                msg.match.set_nw_dst(self.buffer[srcip]['DestinationNetwork'])
                # msg.match.nw_dst = IPAddr(srcip)
                msg.actions.append(
                    of.ofp_action_dl_addr.set_src(
                        EthAddr(self.arp_table[self.routing_table[
                            self.buffer[srcip]['DestinationNetwork']]
                                               ['RouterInterface']])))
                msg.actions.append(
                    of.ofp_action_dl_addr.set_dst(
                        EthAddr(self.arp_table[srcip])))
                msg.actions.append(of.ofp_action_output(port=out_port))
                self.connection.send(msg)
                log.debug(
                    "!LOG! S1 : Flow mod for destination network %s sent!",
                    self.buffer[srcip]['DestinationNetwork'])
                self.buffer.pop(srcip)
Example #50
0
    def _handle_PacketIn(self, event):
        dpid = event.dpid
        inport = event.port
        packet = event.parsed

        if not packet.parsed:
            log.warning("%s: ignoring unparsed packet", dpid_to_str(dpid))
            return

        def drop(duration=None):
            """
            Drops this packet and optionally installs a flow to continue
            dropping similar ones for a while
            """
            if duration is not None:
                if not isinstance(duration, tuple):
                    duration = (duration, duration)
                msg = of.ofp_flow_mod()
                msg.match = of.ofp_match.from_packet(packet)
                msg.idle_timeout = duration[0]
                msg.hard_timeout = duration[1]
                msg.buffer_id = event.ofp.buffer_id
                event.connection.send(msg)
            elif event.ofp.buffer_id is not None:
                msg = of.ofp_packet_out()
                msg.buffer_id = event.ofp.buffer_id
                msg.in_port = event.port
                event.connection.send(msg)

        a = packet.find('arp')
        if not a:
            return

        log.debug("%s ARP %s %s => %s", dpid_to_str(dpid), {
            arp.REQUEST: "request",
            arp.REPLY: "reply"
        }.get(a.opcode, 'op:%i' % (a.opcode, )), str(a.protosrc),
                  str(a.protodst))

        if a.opcode == arp.REQUEST:

            if packet.payload.hwsrc != self.mac and packet.payload.protosrc != self.ip:

                if packet.payload.protodst in arpNat:
                    arpNat[packet.payload.protodst].append([
                        packet.payload.hwsrc, packet.payload.protosrc, dpid,
                        inport
                    ])

                else:
                    arpNat[packet.payload.protodst] = [[
                        packet.payload.hwsrc, packet.payload.protosrc, dpid,
                        inport
                    ]]

                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 = packet.payload.protodst
                r.protosrc = self.ip
                r.hwsrc = self.mac
                e = ethernet(type=ethernet.ARP_TYPE,
                             src=self.mac,
                             dst=ETHER_BROADCAST)
                e.payload = r

                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)
                return EventHalt
            else:
                return

        elif a.opcode == arp.REPLY:
            if (arpNat[packet.payload.protosrc]
                    and packet.payload.protodst == self.ip
                    and packet.payload.hwdst == self.mac):
                drop()
                flag = False
                count = 0

                for e in arpNat[packet.payload.protosrc]:
                    if e[2] == dpid:
                        flag = True
                        i = count
                    count += 1

                if flag:
                    r = arp()
                    r.hwtype = r.HW_TYPE_ETHERNET
                    r.prototype = r.PROTO_TYPE_IP
                    r.hwlen = 6
                    r.protolen = r.protolen
                    r.opcode = r.REPLY
                    r.hwdst, r.protodst, outpid, outport = arpNat[
                        packet.payload.protosrc].pop(i)
                    r.hwsrc = packet.payload.hwsrc
                    r.protosrc = packet.payload.protosrc
                    e = ethernet(type=ethernet.ARP_TYPE,
                                 src=self.mac,
                                 dst=r.hwdst)
                    e.set_payload(r)
                    log.debug("ARPing for %s on behalf of %s" %
                              (r.protodst, r.protosrc))

                    msg = of.ofp_packet_out()
                    msg.data = e.pack()
                    msg.actions.append(of.ofp_action_output(port=outport))
                    msg.in_port = inport
                    event.connection.send(msg)
                    return EventHalt
            else:
                return
    def _handle_openflow_PacketIn(self, event):
        dpid = event.connection.dpid
        inport = event.port
        packet = event.parsed
        global set_Timer
        global defendDDOS
        global blockPort
        timerSet = False
        global diction

        def preventing():
            global diction
            global set_Timer
            if not set_Timer:
                set_Timer = True

            if len(diction) == 0:
                print("Empty diction ", str(event.connection.dpid),
                      str(event.port))
                diction[event.connection.dpid] = {}
                diction[event.connection.dpid][event.port] = 1
            elif event.connection.dpid not in diction:
                diction[event.connection.dpid] = {}
                diction[event.connection.dpid][event.port] = 1
            else:
                if event.connection.dpid in diction:
                    if event.port in diction[event.connection.dpid]:
                        temp_count = 0
                        temp_count = diction[event.connection.dpid][event.port]
                        temp_count = temp_count + 1
                        diction[event.connection.dpid][event.port] = temp_count
                        #print "*****************************************************************************************************************************************************************************"
                        print "dpid port and its packet count: ", str(
                            event.connection.dpid), str(
                                diction[event.connection.dpid]), str(
                                    diction[event.connection.dpid][event.port])
                        #print "*****************************************************************************************************************************************************************************"
                    else:
                        diction[event.connection.dpid][event.port] = 1

        def _timer_func():
            global diction
            global set_Timer

            if set_Timer == True:
                for k, v in diction.iteritems():
                    for i, j in v.iteritems():
                        if j >= 5:
                            print "_____________________________________________________________________________________________"
                            print "\n                               DDOS DETECTED                                              \n"
                            print "\n", str(diction)
                            print "\n", datetime.datetime.now(
                            ), ": BLOCKED PORT NUMBER  : ", str(
                                i), " OF SWITCH ID: ", str(k)
                            print "\n___________________________________________________________________________________________"
                            os._exit(0)
                            dpid = k
                            msg = of.ofp_packet_out(in_port=i)
                            core.openflow.sendToDPID(dpid, msg)
            diction = {}

        if not packet.parsed:
            log.warning("%i %i ignoring unparsed packet", dpid, inport)
            return

        if dpid not in self.arpTable:
            self.arpTable[dpid] = {}
            for fake in self.fakeways:
                self.arpTable[dpid][IPAddr(fake)] = Entry(
                    of.OFPP_NONE, dpid_to_mac(dpid))

        if packet.type == ethernet.LLDP_TYPE:
            return

        if isinstance(packet.next, ipv4):
            log.debug("%i %i IP %s => %s", dpid, inport, packet.next.srcip,
                      packet.next.dstip)
            ent_obj.collectStats(event.parsed.next.dstip)
            print "Entropy : ", str(ent_obj.value)
            if ent_obj.value < 1.0:
                preventing()
                if timerSet is not True:
                    Timer(1, _timer_func, recurring=True)
                    timerSet = False
            else:
                timerSet = False

            self._send_lost_buffers(dpid, packet.next.srcip, packet.src,
                                    inport)

            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)
                    if self.wide:
                        msg = of.ofp_flow_mod(command=of.OFPFC_DELETE)
                        msg.match.nw_dst = packet.next.srcip
                        msg.match.dl_type = ethernet.IP_TYPE
                        event.connection.send(msg)
            else:
                log.debug("%i %i learned %s", dpid, inport, packet.next.srcip)
            self.arpTable[dpid][packet.next.srcip] = Entry(inport, packet.src)

            dstaddr = packet.next.dstip
            if dstaddr in self.arpTable[dpid]:

                prt = self.arpTable[dpid][dstaddr].port
                mac = self.arpTable[dpid][dstaddr].mac
                if prt == inport:
                    log.warning(
                        "%i %i not sending packet for %s back out of the "
                        "input port" % (dpid, inport, dstaddr))
                else:
                    log.debug(
                        "%i %i installing flow for %s => %s out port %i" %
                        (dpid, inport, packet.next.srcip, dstaddr, prt))

                    actions = []
                    actions.append(of.ofp_action_dl_addr.set_dst(mac))
                    actions.append(of.ofp_action_output(port=prt))
                    if self.wide:
                        match = of.ofp_match(dl_type=packet.type,
                                             nw_dst=dstaddr)
                    else:
                        match = of.ofp_match.from_packet(packet, inport)

                    msg = of.ofp_flow_mod(command=of.OFPFC_ADD,
                                          idle_timeout=FLOW_IDLE_TIMEOUT,
                                          hard_timeout=of.OFP_FLOW_PERMANENT,
                                          buffer_id=event.ofp.buffer_id,
                                          actions=actions,
                                          match=match)
                    event.connection.send(msg.pack())
            elif self.arp_for_unknowns:
                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]

                self.outstanding_arps = {
                    k: v
                    for k, v in self.outstanding_arps.iteritems()
                    if v > time.time()
                }

                if (dpid, dstaddr) in self.outstanding_arps:
                    return

                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
                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" %
                          (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)

        elif isinstance(packet.next, arp):
            a = packet.next
            log.debug("%i %i ARP %s %s => %s", dpid, inport, {
                arp.REQUEST: "request",
                arp.REPLY: "reply"
            }.get(a.opcode, 'op:%i' % (a.opcode, )), a.protosrc, a.protodst)

            if a.prototype == arp.PROTO_TYPE_IP:
                if a.hwtype == arp.HW_TYPE_ETHERNET:
                    if a.protosrc != 0:

                        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,
                                         a.protosrc)
                                if self.wide:
                                    msg = of.ofp_flow_mod(
                                        command=of.OFPFC_DELETE)
                                    msg.match.dl_type = ethernet.IP_TYPE
                                    msg.match.nw_dst = a.protosrc
                                    event.connection.send(msg)
                        else:
                            log.debug("%i %i learned %s", dpid, inport,
                                      a.protosrc)
                        self.arpTable[dpid][a.protosrc] = Entry(
                            inport, packet.src)

                        self._send_lost_buffers(dpid, a.protosrc, packet.src,
                                                inport)

                        if a.opcode == arp.REQUEST:

                            if a.protodst in self.arpTable[dpid]:

                                if not self.arpTable[dpid][
                                        a.protodst].isExpired():

                                    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.protodst = a.protosrc
                                    r.protosrc = a.protodst
                                    r.hwsrc = self.arpTable[dpid][
                                        a.protodst].mac
                                    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, 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

            log.debug("%i %i flooding ARP %s %s => %s" % (dpid, inport, {
                arp.REQUEST: "request",
                arp.REPLY: "reply"
            }.get(a.opcode, 'op:%i' % (a.opcode, )), a.protosrc, a.protodst))

            msg = of.ofp_packet_out(
                in_port=inport,
                data=event.ofp,
                action=of.ofp_action_output(port=of.OFPP_FLOOD))
            event.connection.send(msg)
Example #52
0
    def _handle_PacketIn(self, event):

        log.info('Start main funciton')
        dpid = event.connection.dpid
        #log.info('dpid is %s ' %dpid)
        packet = event.parsed  # This is the parsed packet data.
        inport = event.port
        if not packet.parsed:
            log.warning("%s: ignoring unparsed packet", dpid_to_str(dpid))
            return
        packet_in = event.ofp  # The actual ofp_packet_in message.

        #log.info("Installing flow...")
        # Maybe the log statement should have source/destination/port?
        #log.debug('the source MAC is %s' %packet.src)
        #log.debug('the dist MAC is %s' %packet.dst)
        #log.debug('the source port is %s' %packet_in.in_port)
        if dpid == 1:
            _route = _route1
        else:
            _route = _route2
        '***********************ARP**********************************'
        if packet.find("arp"):
            a = packet.find('arp')
            if not a: return
            log.debug("ARP %s %s => %s", {
                arp.REQUEST: "request",
                arp.REPLY: "reply"
            }.get(a.opcode, 'op:%i' % (a.opcode, )), str(a.protosrc),
                      str(a.protodst))
            _ip_to_port[IPAddr(a.protosrc)] = inport

            #Deal with ARP REQUEST then ARP REPLY to hosts
            if a.prototype == arp.PROTO_TYPE_IP and a.hwtype == arp.HW_TYPE_ETHERNET and a.opcode == arp.REQUEST:
                _arp_cache[IPAddr(a.protosrc)] = EthAddr(a.hwsrc)
                #log.info('store to cache %s' %_arp_cache)
                #log.info('self._arp_cache[a.protosrc] = %s protosrc is %s' %(self._arp_cache[IPAddr(a.protosrc)],IPAddr(a.protosrc)))

                if dpid == 2 and inport == 1:
                    p = arp()
                    p.hwtype = arp.HW_TYPE_ETHERNET
                    p.prototype = arp.PROTO_TYPE_IP
                    p.hwlen = 6
                    p.protolen = 4
                    p.opcode = arp.REQUEST
                    p.hwdst = EthAddr('ff:ff:ff:ff:ff:ff')
                    p.hwsrc = EthAddr('00:00:00:00:00:07')
                    p.protodst = _route[2][0]
                    p.protosrc = _route[2][1]

                    E = ethernet(type=ethernet.ARP_TYPE,
                                 src=p.hwsrc,
                                 dst=p.hwdst)
                    E.payload = p
                    self.resend_packet(E, 2)
                elif dpid == 1 and inport == 1:
                    pp = arp()
                    pp.hwtype = arp.HW_TYPE_ETHERNET
                    pp.prototype = arp.PROTO_TYPE_IP
                    pp.hwlen = 6
                    pp.protolen = 4
                    pp.opcode = arp.REQUEST
                    pp.hwdst = EthAddr('ff:ff:ff:ff:ff:ff')
                    pp.hwsrc = EthAddr('00:00:00:00:00:04')
                    pp.protodst = a.protodst
                    pp.protosrc = IPAddr('10.0.1.1')

                    EE = ethernet(type=ethernet.ARP_TYPE,
                                  src=pp.hwsrc,
                                  dst=pp.hwdst)
                    EE.payload = pp

                    self.resend_packet(EE, 2)
                    self.resend_packet(EE, 3)
                else:
                    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.protodst = a.protosrc
                    r.protosrc = a.protodst
                    if str(a.protodst) == '10.0.1.1':
                        r.hwsrc = EthAddr('00:00:00:00:00:04')
                    if str(a.protodst) == '10.0.2.1':
                        r.hwsrc = EthAddr('00:00:00:00:00:07')

                    e = ethernet(type=packet.type, src=r.hwsrc, dst=a.hwsrc)
                    e.payload = r
                    log.info("Answering ARP for %s" % (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)

                    msg1 = of.ofp_flow_mod()
                    msg1.match = of.ofp_match()
                    msg1.match.dl_type = 0x800
                    msg1.match.nw_dst = a.protosrc
                    msg1.actions.append(of.ofp_action_dl_addr.set_src(r.hwsrc))
                    msg1.actions.append(of.ofp_action_dl_addr.set_dst(r.hwdst))
                    msg1.actions.append(of.ofp_action_output(port=inport))
                    self.connection.send(msg1)

            #Deal with ARP REPLY and store ARP cache
            #Prepare to send  buffered ICMP REQUEST packets with new MAC address
            if a.prototype == arp.PROTO_TYPE_IP and a.hwtype == arp.HW_TYPE_ETHERNET and a.opcode == arp.REPLY:
                _arp_cache[IPAddr(a.protosrc)] = EthAddr(a.hwsrc)

                msg2 = of.ofp_flow_mod()
                msg2.match = of.ofp_match()
                msg2.match.dl_type = 0x800
                msg2.match.nw_dst = a.protosrc
                msg2.actions.append(of.ofp_action_dl_addr.set_src(a.hwdst))
                msg2.actions.append(of.ofp_action_dl_addr.set_dst(a.hwsrc))
                msg2.actions.append(of.ofp_action_output(port=inport))
                self.connection.send(msg2)

                self.msg_send(_buff[IPAddr(a.protosrc)], a.hwdst, a.hwsrc,
                              inport)
                #self.icmp_forward(_buff[IPAddr(a.protosrc)],TYPE_ECHO_REQUEST,_ip_bf[IPAddr(a.protosrc)].srcip,_ip_bf[IPAddr(a.protosrc)].dstip,a.hwdst,a.hwsrc,inport)
                log.info('forward dic %s' % _buff[IPAddr(a.protosrc)])
        '****************************ICMP***********************'
        if packet.find("icmp"):
            log.info('ICMP occurs')
            _ip_to_port[IPAddr(packet.payload.srcip)] = inport

            #intall the packet and get information of the packet
            #rqt_src: router interface IP addr; rqt_port: router port; rqt_pfx: network prefix; rqt_hwsrc: router interface MAC addr.

            payload_bf = packet.payload.payload.payload
            icmp_bf = packet.payload.payload

            #log.info('icmp type =%s'%packet.payload.payload.type)
            global rqtsrc, rqtdst, rqtport, rqtpfx, rqthwsrc
            global rplsrc, rpldst, rplport, rplpfx, rplhwsrc
            #log.debug('before loop:')
            #log.info('icmp cache is %s' %_arp_cache)
            target = 0
            for j in range(0, 5):
                for i in range(0, 3):
                    if str(_route[i][j]) == str(packet.payload.dstip):
                        if j == 0:
                            rqtsrc = _route[i][1]
                            rqtdst = _route[i][0]
                            rqtport = _route[i][2]
                            rqtpfx = _route[i][3]
                            rqthwsrc = _route[i][4]
                            #target = 1 means the icmp packet is to host
                            target = 1
                            break
                        elif j == 1:
                            #router reply to host
                            rplsrc = _route[i][1]
                            rpldst = _route[i][0]
                            rplport = _route[i][2]
                            rplpfx = _route[i][3]
                            rplhwsrc = _route[i][4]
                            #target = 2 means the icmp packet is to router interface
                            target = 2
                            flagd = i
                            break
            for k in range(0, 3):
                if str(_route[k][0]) == str(packet.payload.srcip):
                    interfaceip = _route[k][1]
                    interfacedst = _route[k][0]
                    flags = _route[k][2]
                    break

            '*********ICMP REQUEST***'
            if target == 0:
                log.info('unknown')
                self.icmp_unknownhost(packet, interfaceip, inport)
                log.info('unknown from %s' % interfaceip)

            elif packet.payload.payload.type == 8 and target != 0:
                #If we do not have IP_MAC in routing table, create ARP Request
                if packet.payload.dstip not in _arp_cache:
                    self.arp_request(packet, _arp_cache[rqthwsrc], rqthwsrc,
                                     rqtport)
                    _buff[IPAddr(packet.payload.dstip)] = packet
                    _ip_bf[IPAddr(packet.payload.dstip)] = packet.payload
                    #log.info('buff %s' %_buff)
                #If we have IP_MAC in routing table, forward packet directly
                elif packet.payload.dstip in _arp_cache:
                    if target == 1:
                        if dpid == 1:
                            if rqtport != 1:
                                #h3 ICMP request forward to h4
                                self.icmp_forward(
                                    packet.payload.payload.payload,
                                    TYPE_ECHO_REQUEST, packet.payload.srcip,
                                    packet.payload.dstip, rqthwsrc,
                                    _arp_cache[IPAddr(packet.payload.dstip)],
                                    rqtport)
                            else:
                                #s1 ICMP request forward to s2
                                self.msg_send(packet, packet.src, packet.dst,
                                              1)
                        else:
                            if inport == 1:
                                #s2 have to forward it to h5
                                self.icmp_forward(
                                    packet.payload.payload.payload,
                                    TYPE_ECHO_REQUEST, packet.payload.srcip,
                                    packet.payload.dstip, _arp_cache[rqtsrc],
                                    _arp_cache[IPAddr(packet.payload.dstip)],
                                    rqtport)
                            else:
                                #s2 give it to s1
                                self.msg_send(packet, packet.src, packet.dst,
                                              1)
                    elif target == 2:
                        #log.debug('icmp cache %s' %_arp_cache)
                        #log.info('flags is %s' %flags)
                        #log.info('dpid is %s, rplport is %s, dstinterface is %s' %(dpid, rplport,interfaceip))
                        if dpid == 1:
                            if rplport != inport:
                                #ping other gateway
                                self.icmp_forward(payload_bf, TYPE_ECHO_REPLY,
                                                  rplsrc, interfacedst,
                                                  packet.dst, packet.src,
                                                  inport)
                            else:
                                #ping default gateway
                                self.icmp_forward(payload_bf, TYPE_ECHO_REPLY,
                                                  rplsrc, rpldst, rplhwsrc,
                                                  _arp_cache[IPAddr(rpldst)],
                                                  rplport)
                        else:
                            if flags == flagd:
                                #ping default gateway
                                self.icmp_forward(payload_bf, TYPE_ECHO_REPLY,
                                                  rplsrc, rpldst, rplhwsrc,
                                                  _arp_cache[IPAddr(rpldst)],
                                                  rplport)
                            else:
                                #ping other gateway
                                self.icmp_forward(payload_bf, TYPE_ECHO_REPLY,
                                                  interfaceip, interfacedst,
                                                  packet.dst, packet.src,
                                                  inport)
            ############ICMP REPLY###############
            #Receive ICPM Reply, we need forward the the reply
            elif packet.payload.payload.type == 0:
                if dpid == 2:
                    #h5 reply to h3
                    if inport == 2:
                        log.info('flow mod starts 1')
                        msg0 = of.ofp_flow_mod()
                        msg0.match = of.ofp_match()
                        msg0.match.dl_type = 0x800
                        msg0.match.nw_dst = packet.payload.dstip
                        msg0.actions.append(
                            of.ofp_action_dl_addr.set_src(_port_to_mac_2['1']))
                        msg0.actions.append(
                            of.ofp_action_dl_addr.set_dst(_port_to_mac_1['1']))
                        msg0.actions.append(of.ofp_action_output(port=1))
                        log.info('flow mod ends 1')
                        self.connection.send(msg0)

                        self.msg_send(packet, packet.src, packet.dst, 1)
                    else:
                        self.msg_send(packet, rqthwsrc,
                                      _arp_cache[packet.payload.dstip],
                                      rqtport)
                elif dpid == 1 and rqtport != 1:
                    #h3 and h4 want to receive
                    if inport != 1:
                        self.icmp_forward(
                            packet.payload.payload.payload, TYPE_ECHO_REPLY,
                            packet.payload.srcip, packet.payload.dstip,
                            rqthwsrc, _arp_cache[IPAddr(packet.payload.dstip)],
                            rqtport)
                    else:
                        self.msg_send(packet, rqthwsrc,
                                      _arp_cache[packet.payload.dstip],
                                      rqtport)
                else:
                    log.info('flow mod starts 2')
                    msg3 = of.ofp_flow_mod()
                    msg3.match = of.ofp_match()
                    msg3.match.dl_type = 0x800
                    msg3.match.nw_dst = packet.payload.dstip
                    msg3.actions.append(
                        of.ofp_action_dl_addr.set_src(_port_to_mac_1['1']))
                    msg3.actions.append(
                        of.ofp_action_dl_addr.set_dst(_port_to_mac_2['1']))
                    msg3.actions.append(of.ofp_action_output(port=1))
                    log.info('flow mod end 2')
                    self.connection.send(msg3)

                    self.msg_send(packet, packet.src, packet.dst, 1)
                    #log.info('ICMP reply for h5 from s1 to s2')
        #########TCP+UDP############
        elif packet.find("ipv4"):
            log.info('TCP occurs')
            for i in range(0, 3):
                if str(_route[i][0]) == str(packet.payload.dstip):
                    tcpsrc = _route[i][1]
                    tcpdst = _route[i][0]
                    tcpport = _route[i][2]
                    tcppfx = _route[i][3]
                    tcphwsrc = _route[i][4]
                    break
            if packet.payload.dstip in _arp_cache:
                if dpid == 1:
                    if tcpport == 1:
                        #s1 send the request to s2
                        self.msg_send(packet, _port_to_mac_1['1'],
                                      _port_to_mac_2['1'], 1)
                    else:
                        #s1 send the request to h4
                        self.msg_send(packet, tcphwsrc, _arp_cache[tcpdst],
                                      tcpport)
                else:
                    #s2 received a request
                    if inport == 1:
                        #s2 send the request to h5
                        self.msg_send(packet, tcphwsrc, _arp_cache[tcpdst],
                                      tcpport)
                    else:
                        #s2 send to s1
                        self.msg_send(packet, _port_to_mac_2['1'],
                                      _port_to_mac_1['1'], 1)
            else:
                #not in cache
                _buff[IPAddr(packet.payload.dstip)] = packet
                if dpid == 1:
                    if tcpport == 1:
                        #s1 send the arp request to s2
                        self.arp_request(packet,
                                         _arp_cache[_port_to_mac_1['1']],
                                         _port_to_mac_1['1'], 1)
                    else:
                        #s1 broadcast arp request
                        self.arp_request(packet, tcpsrc, tcphwsrc, 2)
                        self.arp_request(packet, tcpsrc, tcphwsrc, 3)
                else:
                    #s2 send the arp request to s1
                    self.arp_request(packet, _arp_cache[_port_to_mac_2['1']],
                                     _port_to_mac_2['1'], 1)
Example #53
0
    def _handle_PacketIn(self, event):
        dpid = event.connection.dpid
        inport = event.port
        packet = event.parsed
        if not packet.parsed:
            log.warning("%i %i ignoring unparsed packet", dpid, inport)
            return

        if dpid not in self.ip_mac_port:
            self.ip_mac_port[dpid] = {}
            for fake in self.fakeways:
                self.ip_mac_port[dpid][IPAddr(fake)] = Entry(
                    of.OFPP_NONE, dpid_to_mac(dpid))

        if packet.type == ethernet.LLDP_TYPE:
            return

        if isinstance(packet.next, ipv4):
            log.debug("%i %i IP %s => %s", dpid, inport, packet.next.srcip,
                      packet.next.dstip)

            self._send_lost_buffers(dpid, packet.next.srcip, packet.src,
                                    inport)

            if packet.next.srcip in self.ip_mac_port[dpid]:
                if self.ip_mac_port[dpid][packet.next.srcip] != (inport,
                                                                 packet.src):
                    log.debug("%i %i RE-learned %s", dpid, inport,
                              packet.next.srcip)
            else:
                #log.info("%i %i learned %s", dpid,inport,str(packet.next.srcip))
                log.info("switch %i learned %s from input port %i", dpid,
                         str(packet.next.srcip), inport)
            self.ip_mac_port[dpid][packet.next.srcip] = Entry(
                inport, packet.src)

            dstaddr = packet.next.dstip
            if dstaddr in self.ip_mac_port[dpid]:

                prt = self.ip_mac_port[dpid][dstaddr].port
                mac = self.ip_mac_port[dpid][dstaddr].mac
                print dstaddr
                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))

                    if event.ofp.buffer_id == None:
                        bid = None
                    else:
                        bid = event.ofp.buffer_id

                    ip_packet = packet.find("ipv4")
                    if ip_packet != None:

                        if ip_packet.protocol == 1:
                            actions3 = []
                            actions3.append(of.ofp_action_dl_addr.set_dst(mac))
                            #actions3.append(of.ofp_action_output(port = prt))
                            actions3.append(
                                of.ofp_action_enqueue(port=prt, queue_id=1))
                            match3 = of.ofp_match.from_packet(packet, inport)
                            match3.dl_type = 0x800
                            match3.nw_proto = 1
                            match3.dl_src = None
                            msg3 = of.ofp_flow_mod(
                                command=of.OFPFC_ADD,
                                idle_timeout=FLOW_IDLE_TIMEOUT,
                                hard_timeout=of.OFP_FLOW_PERMANENT,
                                buffer_id=bid,
                                actions=actions3,
                                priority=30,
                                match=match3)
                            event.connection.send(msg3.pack())
                            print "into queue 1"
                        elif ip_packet.protocol == 17 or ip_packet.protocol == 6:
                            udp_packet = packet.find("udp")
                            if udp_packet == None:
                                udp_packet = packet.find("tcp")
                            if ip_packet.dstip == IPAddr(
                                    "172.16.0.3"
                            ) and udp_packet.dstport == 5001:
                                actions5 = []
                                actions5.append(
                                    of.ofp_action_dl_addr.set_dst(mac))
                                #actions5.append(of.ofp_action_output(port = prt))
                                actions5.append(
                                    of.ofp_action_enqueue(port=prt,
                                                          queue_id=3))
                                match5 = of.ofp_match.from_packet(
                                    packet, inport)
                                match5.dl_type = 0x800
                                match5.nw_proto = 17
                                match5.nw_dst = IPAddr("172.16.0.3")
                                match5.tp_dst = 5001
                                match5.dl_src = None
                                msg5 = of.ofp_flow_mod(
                                    command=of.OFPFC_ADD,
                                    idle_timeout=FLOW_IDLE_TIMEOUT,
                                    hard_timeout=of.OFP_FLOW_PERMANENT,
                                    buffer_id=bid,
                                    actions=actions5,
                                    priority=43,
                                    match=match5)
                                event.connection.send(msg5.pack())
                                print "privillaged user into queue 3"
                            elif ip_packet.tos == 0:
                                actions2 = []
                                actions2.append(
                                    of.ofp_action_dl_addr.set_dst(mac))
                                #actions2.append(of.ofp_action_output(port = prt))
                                actions2.append(of.ofp_action_nw_tos(224))
                                actions2.append(
                                    of.ofp_action_enqueue(port=prt,
                                                          queue_id=2))
                                match2 = of.ofp_match.from_packet(
                                    packet, inport)
                                match2.dl_type = 0x800
                                if udp_packet != None:
                                    match2.nw_proto = 17
                                else:
                                    match2.nw_proto = 6
                                match2.dl_src = None
                                msg2 = of.ofp_flow_mod(
                                    command=of.OFPFC_ADD,
                                    idle_timeout=FLOW_IDLE_TIMEOUT,
                                    hard_timeout=of.OFP_FLOW_PERMANENT,
                                    buffer_id=bid,
                                    actions=actions2,
                                    priority=42,
                                    match=match2)
                                event.connection.send(msg2.pack())
                                print "into queue 2"
                            else:
                                actions1 = []
                                actions1.append(
                                    of.ofp_action_dl_addr.set_dst(mac))
                                #actions1.append(of.ofp_action_output(port = prt))
                                actions1.append(
                                    of.ofp_action_enqueue(port=prt,
                                                          queue_id=2))
                                match1 = of.ofp_match.from_packet(
                                    packet, inport)
                                match1.dl_type = 0x800
                                match1.nw_tos = 224
                                match1.dl_src = None
                                msg1 = of.ofp_flow_mod(
                                    command=of.OFPFC_ADD,
                                    idle_timeout=FLOW_IDLE_TIMEOUT,
                                    hard_timeout=of.OFP_FLOW_PERMANENT,
                                    buffer_id=bid,
                                    actions=actions1,
                                    priority=42,
                                    match=match1)
                                event.connection.send(msg1.pack())
                                print "into queue 2 dscp tagged"
                    else:
                        actions = []
                        actions.append(of.ofp_action_dl_addr.set_dst(mac))
                        actions.append(of.ofp_action_output(port=prt))
                        match4 = of.ofp_match.from_packet(packet, inport)
                        match4.dl_src = None  # Wildcard source MAC

                        msg = of.ofp_flow_mod(
                            command=of.OFPFC_ADD,
                            idle_timeout=FLOW_IDLE_TIMEOUT,
                            hard_timeout=of.OFP_FLOW_PERMANENT,
                            buffer_id=bid,
                            actions=actions,
                            priority=20,
                            match=match4)
                        event.connection.send(msg.pack())

            elif self.arp_for_unknowns:
                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]

                self.outstanding_arps = {
                    k: v
                    for k, v in self.outstanding_arps.iteritems()
                    if v > time.time()
                }

                if (dpid, dstaddr) in self.outstanding_arps:
                    return

                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
                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" %
                          (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
            log.debug("%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.ip_mac_port[dpid]:
                            if self.ip_mac_port[dpid][a.protosrc] != (
                                    inport, packet.src):
                                log.debug("%i %i RE-learned %s", dpid, inport,
                                          str(a.protosrc))
                        else:
                            log.info("switch %i learned %s from input port %i",
                                     dpid, str(a.protosrc), inport)
                        self.ip_mac_port[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.REQUEST:
                            # Maybe we can answer

                            if a.protodst in self.ip_mac_port[dpid]:
                                # We have an answer...

                                if not self.ip_mac_port[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.protodst = a.protosrc
                                    r.protosrc = a.protodst
                                    r.hwsrc = self.ip_mac_port[dpid][
                                        a.protodst].mac
                                    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)))

            msg = of.ofp_packet_out(
                in_port=inport,
                data=event.ofp,
                action=of.ofp_action_output(port=of.OFPP_FLOOD))
            event.connection.send(msg)
Example #54
0
    def _handle_PacketIn(self, event):

        # parsing the input packet
        packet = event.parse()

        # If no switch has ever seen this host before, then it must be directly
        # connected to us!  Record that in our global list.
        if packet.src not in self.hostlocations or self.hostlocations[
                packet.src]["lastseen"] < (datetime.now() -
                                           timedelta(0, IDLE_TIMEOUT)):
            #log.debug("s%s takes ownership of host %s" % (self.connection.ID, packet.src))
            self.hostlocations[packet.src] = {
                "ID": self.connection.ID,
                "lastseen": datetime.now()
            }

            # Record which hosts exists on which of our ports
            ip = GetIPFromMAC(packet.src)
            if ip is not None:
                #log.debug("    on IP '%s'" % ip)
                self.hostports[event.port] = packet.src

        elif self.hostlocations[packet.src]["ID"] == self.connection.ID:
            #log.debug("s%s continues to own host %s" % (datetime.now(), self.connection.ID, packet.src))
            self.hostlocations[packet.src]["lastseen"] = datetime.now()

        # Keep a list of which MAC addresses live on which port, so we can forward
        # packets as needed
        if packet.src not in self.mactable or self.mactable[
                packet.src] != event.ofp.in_port:
            self.mactable[packet.src] = event.ofp.in_port
            #log.debug("Learned port %s connects to %s" % (event.ofp.in_port, packet.src))

        if packet.type == packet.LLDP_TYPE or packet.type == 0x86DD:
            # Drop LLDP packets
            # Drop IPv6 packets
            # send of command without actions

            msg = of.ofp_packet_out()
            msg.buffer_id = event.ofp.buffer_id
            msg.in_port = event.port
            self.connection.send(msg)
            return

        # Watch for ARP packets trying to discover a load-balance target.
        packet_arp = packet.find('arp')
        if packet_arp is not None and str(
                packet_arp.protodst).startswith(LOADBALANCE_TARGET):
            # Found one!  Respond with a special MAC address, which our switches will
            # be able to identify easily for load-balancing.
            #log.debug('ARP Packet!!!! Looking for %s' % packet_arp.protodst)
            mac = GetMACForLoadBalancing()

            reply_arp = arp()
            reply_arp.hwtype = packet_arp.hwtype
            reply_arp.prototype = packet_arp.prototype
            reply_arp.hwlen = packet_arp.hwlen
            reply_arp.protolen = packet_arp.protolen
            reply_arp.opcode = arp.REPLY
            reply_arp.hwdst = packet_arp.hwsrc
            reply_arp.hwsrc = mac
            reply_arp.protodst = packet_arp.protosrc
            reply_arp.protosrc = packet_arp.protodst
            reply_eth = ethernet(type=packet.type,
                                 src=mac,
                                 dst=packet_arp.hwsrc)
            reply_eth.payload = reply_arp
            reply = of.ofp_packet_out(in_port=of.OFPP_NONE)
            reply.actions.append(of.ofp_action_output(port=event.port))
            reply.data = reply_eth.pack()
            event.connection.send(reply)
            return

        # If this packet is being delivered to a special MAC, set up some flows to
        # get the data to the right place.
        packet_ipv4 = packet.find('ipv4')
        if IsMACForLoadBalancing(packet.dst) and packet_ipv4 is not None:
            eligibleports = []
            for port in self.connection.features.ports:
                if port.port_no != event.port and not port.config & OFPPC_PORT_DOWN:
                    eligibleports.append(port.port_no)
            port_out = random.choice(eligibleports)

            # Establish bi-directional flows!
            log.debug("Establishing load-balancing flows for %s <--> %s" %
                      (packet.src, packet.dst))
            flow_in = of.ofp_flow_mod()
            flow_out = of.ofp_flow_mod()
            flow_in.idle_timeout = flow_out.idle_timeout = IDLE_TIMEOUT
            flow_in.hard_timeout = flow_out.hard_timeout = HARD_TIMEOUT
            flow_in.match = of.ofp_match(dl_dst=packet.src, dl_src=packet.dst)
            flow_out.match = of.ofp_match(dl_dst=packet.dst, dl_src=packet.src)

            if port_out in self.hostports:
                # If we're delivering to a host (instead of another switch), we need
                # to rewrite some of the packet data, so that things line up properly
                # on each end.  The sender sends to the special IP, and the receiver
                # should see the packet addressed to itself (and vice versa).
                log.debug("...which will be handled by %s" %
                          (self.hostports[port_out]))
                flow_in.actions.append(
                    of.ofp_action_dl_addr(of.OFPAT_SET_DL_SRC, packet.dst))
                flow_in.actions.append(
                    of.ofp_action_nw_addr(of.OFPAT_SET_NW_SRC,
                                          packet_ipv4.dstip))
                flow_out.actions.append(
                    of.ofp_action_dl_addr(of.OFPAT_SET_DL_DST,
                                          self.hostports[port_out]))
                flow_out.actions.append(
                    of.ofp_action_nw_addr(
                        of.OFPAT_SET_NW_DST,
                        GetIPFromMAC(self.hostports[port_out])))

                # We also need to update one of our match rules, since the packet will
                # be sent with a non-special MAC address.
                flow_in.match.dl_src = self.hostports[port_out]

            flow_in.actions.append(of.ofp_action_output(port=event.port))
            flow_out.actions.append(of.ofp_action_output(port=port_out))
            flow_in.in_port = port_out
            flow_out.in_port = event.port
            flow_out.data = event.ofp
            self.connection.send(flow_in)
            self.connection.send(flow_out)
            return

        elif packet.dst in self.mactable:
            # If we know the destination, but are being told about it, recreate the
            # flow, since this is either the initial discovery, or the flow expired.
            log.debug(
                "Establishing flow to deliver packets for %s to port %s" %
                (packet.dst, self.mactable[packet.dst]))
            fm = of.ofp_flow_mod()
            fm.idle_timeout = IDLE_TIMEOUT
            fm.hard_timeout = HARD_TIMEOUT
            fm.actions.append(
                of.ofp_action_output(port=self.mactable[packet.dst]))

            # Defining the match via from_packet will cause us to establish a flow
            # for each unique packet type per destination, instead of just per dest.
            fm.match = of.ofp_match(dl_dst=packet.dst, dl_src=packet.src)
            #fm.match = of.ofp_match.from_packet(packet)

            fm.data = event.ofp  # Deliver the packet along this flow
            self.connection.send(fm)
            return

        log.debug("Port for %s unknown -- flooding" % (packet.dst, ))
        msg = of.ofp_packet_out()
        msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD))
        msg.buffer_id = event.ofp.buffer_id
        msg.in_port = event.port
        self.connection.send(msg)
Example #55
0
        def forward(message=None):
            # dpid => switch (i)
            dpid = event.connection.dpid
            # port of a switch
            inport = event.port
            packet = event.parsed

            log.debug("Add to forward table src=%s, port=%s" %
                      (packet.src, event.port))
            # self.macToPort[packet.src] = event.port

            if dpid not in self.forwardTable:
                self.forwardTable[dpid] = {}

            if packet.type == ethernet.LLDP_TYPE:
                # Ignore LLDP packets
                return

            if isinstance(packet.next, ipv4):
                log.debug("IPV4 packet s=%i, sp=%i src=%s => dst=%s", dpid,
                          inport, packet.next.srcip, packet.next.dstip)

                if (packet.next.protocol == packet.next.TCP_PROTOCOL):
                    # Get TCP payload in IPv4
                    tcpPacket = packet.next.payload
                    log.debug("TCP payload srcport= %s dstport=%s",
                              str(tcpPacket.srcport), str(tcpPacket.dstport))

                    # Check firewall
                    if self.check_rule(packet.next.srcip, packet.next.dstip,
                                       tcpPacket.dstport) or self.check_rule(
                                           packet.next.dstip,
                                           packet.next.srcip,
                                           tcpPacket.dstport):
                        log.warning(
                            "Firewall DROP between %s <--> %s on port %s",
                            str(packet.next.srcip), str(packet.next.dstip),
                            str(tcpPacket.dstport))
                        drop(priorityFirewall)
                        return

                # Send any waiting packets...
                self._send_lost_buffers(dpid, packet.next.srcip, packet.src,
                                        inport)

                # Learn or update forwarding table
                log.debug("s=%i, sp=%i LEARN or UPDATE src=%s", dpid, inport,
                          str(packet.next.srcip))
                self.forwardTable[dpid][packet.next.srcip] = Entry(
                    inport, packet.src)

                # Try to forward to destination by checking port
                dstip = packet.next.dstip
                if (dstip in self.forwardTable[dpid]):
                    # Got the port info to send out
                    dstport = self.forwardTable[dpid][dstip].port
                    dstmac = self.forwardTable[dpid][dstip].mac

                    if dstport == inport:
                        # Same port for destination and switch..
                        log.warning(
                            "s=%i, sp=%i NOT SEND PACKET for dst=%s with same port"
                            % (dpid, inport, str(dstip)))
                    else:
                        log.debug(
                            "s=%i, sp=%i INSTALL FLOW for src=%s => dst=%s out port=%i"
                            %
                            (dpid, inport, packet.next.srcip, dstip, dstport))

                        actions = []
                        if self.check_premium(packet.next.dstip):
                            actions.append(
                                of.ofp_action_enqueue(port=dstport,
                                                      queue_id=1))
                        else:
                            actions.append(of.ofp_action_output(port=dstport))

                        # actions.append(of.ofp_action_output(port = dstport))
                        actions.append(of.ofp_action_dl_addr.set_dst(dstmac))
                        match = of.ofp_match.from_packet(packet, inport)
                        match.dl_src = None  # Wildcard source MAC

                        msg = of.ofp_flow_mod(
                            command=of.OFPFC_ADD,
                            idle_timeout=FLOW_IDLE_TIMEOUT,
                            hard_timeout=of.OFP_FLOW_PERMANENT,
                            buffer_id=event.ofp.buffer_id,
                            actions=actions,
                            match=of.ofp_match.from_packet(packet, inport))
                        msg.priority = priorityPremium
                        # if self.check_premium(packet.next.dstip):
                        #     log.debug("PRIORITY dst ip=%s has priority of 100!!!!!" % packet.next.dstip)
                        #     msg.priority = 100
                        # else:
                        #     log.debug("PRIORITY dst ip=%s has priority of 1...." % packet.next.dstip)
                        #     msg.priority = 1

                        # event.connection.send(msg.pack())
                        event.connection.send(msg)

            elif isinstance(packet.next, arp):
                pktnext = packet.next

                if pktnext.prototype == arp.PROTO_TYPE_IP:
                    if pktnext.hwtype == arp.HW_TYPE_ETHERNET:
                        if pktnext.protosrc != 0:

                            # Learn or update port, mac info
                            self.forwardTable[dpid][pktnext.protosrc] = Entry(
                                inport, packet.src)

                            # Send any waiting packets...
                            self._send_lost_buffers(dpid, pktnext.protosrc,
                                                    packet.src, inport)

                            if pktnext.opcode == arp.REQUEST:
                                if pktnext.protodst in self.forwardTable[dpid]:
                                    # Reply ARP back
                                    r = arp()
                                    r.hwtype = pktnext.hwtype
                                    r.prototype = pktnext.prototype
                                    r.hwlen = pktnext.hwlen
                                    r.protolen = pktnext.protolen
                                    r.opcode = arp.REPLY
                                    r.hwdst = pktnext.hwsrc
                                    r.protodst = pktnext.protosrc
                                    r.protosrc = pktnext.protodst
                                    r.hwsrc = self.forwardTable[dpid][
                                        pktnext.protodst].mac
                                    e = ethernet(type=packet.type,
                                                 src=dpid_to_mac(dpid),
                                                 dst=pktnext.hwsrc)
                                    e.set_payload(r)
                                    log.debug("s=%i sp=%i answer 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

                log.debug("s=%i sp=%i FLOOD ARP %s %s => %s" %
                          (dpid, inport, {
                              arp.REQUEST: "request",
                              arp.REPLY: "reply"
                          }.get(pktnext.opcode, 'op:%i' % (pktnext.opcode, )),
                           str(pktnext.protosrc), str(pktnext.protodst)))
                msg = of.ofp_packet_out(
                    in_port=inport,
                    data=event.ofp,
                    action=of.ofp_action_output(port=of.OFPP_FLOOD))
                # msg.priority = priorityLearn
                event.connection.send(msg)
  def _handle_addFlowEntry (self,event):

    FLOW_IDLE_TIMEOUT = event.idleTimeout
    FLOW_HARD_TIMEOUT = event.hardTimeout
    event = event.event
    dpid = event.connection.dpid
    inport = event.port
    packet = 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))

    if packet.type == ethernet.LLDP_TYPE:
      # Ignore LLDP packets
      return

    if isinstance(packet.next, ipv4):
      log.debug("%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)

      # 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)

      # Try to forward
      dstaddr = packet.next.dstip
      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
        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))

          actions = []
          actions.append(of.ofp_action_dl_addr.set_dst(mac))
          actions.append(of.ofp_action_output(port = prt))
          match = of.ofp_match.from_packet(packet, inport)
          match.dl_src = None # Wildcard source MAC

          msg = of.ofp_flow_mod(command=of.OFPFC_ADD,
                                idle_timeout=FLOW_IDLE_TIMEOUT,
                                hard_timeout=FLOW_HARD_TIMEOUT,
                                buffer_id=event.ofp.buffer_id,
                                actions=actions,
                                flags=of.OFPFF_SEND_FLOW_REM,
                                match=of.ofp_match.from_packet(packet,
                                                               inport))
          event.connection.send(msg.pack())
      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
        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" % (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
      log.debug("%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.REQUEST:
              # Maybe we can answer

              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.protodst = a.protosrc
                  r.protosrc = a.protodst
                  r.hwsrc = self.arpTable[dpid][a.protodst].mac
                  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)))

      msg = of.ofp_packet_out(in_port = inport, data = event.ofp,
          action = of.ofp_action_output(port = of.OFPP_FLOOD))
      event.connection.send(msg)
Example #57
0
             EthAddr('00:00:00:00:00:07'))])
_port_to_mac_1 = {
    '1': EthAddr('00:00:00:00:00:05'),
    '2': EthAddr('00:00:00:00:00:04'),
    '3': EthAddr('00:00:00:00:00:04')
}
_port_to_mac_2 = {
    '1': EthAddr('00:00:00:00:00:06'),
    '2': EthAddr('00:00:00:00:00:07')
}
_ip_to_port = {}
rqtsrc, rqtdst, rqtport, rqtpfx, rqthwsrc = 0, 0, 0, 0, 0
rplsrc, rpldst, rplport, rplpfx, rplhwsrc = 0, 0, 0, 0, 0
icmpf = icmp()
ip_pakt = ipv4()
eth = ethernet()
_buff = {}
_ip_bf = {}


class controller3(object):
    '**********begin***************************'

    def __init__(self, connection):
        # Keep track of the connection to the switch so that we can
        # send it messages!
        self.connection = connection

        # This binds our PacketIn event listener
        connection.addListeners(self)
Example #58
0
  def _handle_PacketIn (self, event):
    dpid = event.connection.dpid
    inport = event.port
    packet = event.parsed
    if not packet.parsed:
      log.warning("%i %i ignoring unparsed packet", dpid, inport)
      return

    if dpid not in self.arpTable:
      self.arpTable[dpid] = {}
 
    if packet.type == ethernet.LLDP_TYPE:
      return

    if isinstance(packet.next, ipv4):
      log.debug("%i %i IP %s => %s", dpid,inport,packet.next.srcip,packet.next.dstip)
      self.sendWaitingPackets (dpid, packet.next.srcip, packet.src, inport)
      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)

      prt = 0
      dstaddr = packet.next.dstip
	  
      prt = self.ip_to_port.get(dstaddr)
      if prt != None:
        log.debug("Got port %i from dictionary",prt)
        mac = None
        if dstaddr in self.arpTable[dpid]:
          mac = self.arpTable[dpid][dstaddr].mac
        if mac!=None:
          actions = []
          actions.append(of.ofp_action_dl_addr.set_dst(mac))
          actions.append(of.ofp_action_dl_addr.set_src(dpid_to_mac(dpid)))
          actions.append(of.ofp_action_output(port = prt))
          match = of.ofp_match.from_packet(packet, inport)
          match.dl_src = None

          msg = of.ofp_flow_mod(command=of.OFPFC_ADD,buffer_id=event.ofp.buffer_id,actions=actions,match=of.ofp_match.from_packet(packet,inport))
          event.connection.send(msg.pack())
          return
        else:
        # Add to tracked buffers
          if (dpid,dstaddr) not in self.message_queue:
            self.message_queue[(dpid,dstaddr)] = []
          bucket = self.message_queue[(dpid,dstaddr)]
          entry = (None,event.ofp.buffer_id,inport)
          bucket.append(entry)
              
          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 = dstaddr
          r.hwsrc = dpid_to_mac(dpid)
          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" % (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) 
	
      else:
	icmpflag = 0	  
        for list in self.routingTable[dpid]:
          if list[0] == str(dstaddr):
            log.debug("Searching Routing Table for IP address: %s ",str(dstaddr))
            prt = list[4]
          if list[3] == str(dstaddr):
            prt = list[4]
            icmpflag = 1
            self.arpTable[dpid][dstaddr] = Entry(prt, dpid_to_mac(dpid))
	
        if icmpflag == 1:
          icmp = pkt.icmp()
          icmp.type = pkt.TYPE_ECHO_REPLY
    	  icmp.payload = packet.find("icmp").payload

    	  # Make the IP packet around it
    	  ipp = pkt.ipv4()
    	  ipp.protocol = ipp.ICMP_PROTOCOL
    	  ipp.srcip = packet.find("ipv4").dstip
    	  ipp.dstip = packet.find("ipv4").srcip

    	  # Ethernet around that...
    	  e = pkt.ethernet()
    	  e.src = packet.dst
    	  e.dst = packet.src
    	  e.type = e.IP_TYPE

    	  # Hook them up...
    	  ipp.payload = icmp
    	  e.payload = ipp

    	  # 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 = e.pack()
    	  msg.in_port = event.port
    	  event.connection.send(msg)
          return

        if prt == None:
          log.debug("Unreachable IP Address : %s",str(dstaddr))
          icmp = pkt.icmp()
          icmp.type = 3
    	  #icmp.payload = packet.find("icmp").payload

    	  # Make the IP packet around it
    	  ipp = pkt.ipv4()
    	  ipp.protocol = ipp.ICMP_PROTOCOL
    	  ipp.srcip = packet.find("ipv4").dstip
    	  ipp.dstip = packet.find("ipv4").srcip

    	  # Ethernet around that...
    	  e = pkt.ethernet()
    	  e.src = packet.dst
    	  e.dst = packet.src
    	  e.type = e.IP_TYPE

    	  # Hook them up...
    	  ipp.payload = icmp
    	  e.payload = ipp

    	  # 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 = e.pack()
    	  msg.in_port = event.port
    	  event.connection.send(msg)
          return
          
        log.debug("Got Port Number : %s from routing table",prt)
        self.ip_to_port[dstaddr] = prt
        mac = None
        if dstaddr in self.arpTable[dpid]:
          mac = self.arpTable[dpid][dstaddr].mac
        if mac!=None:
          actions = []
          actions.append(of.ofp_action_dl_addr.set_dst(mac))
          actions.append(of.ofp_action_dl_addr.set_src(dpid_to_mac(dpid)))
          actions.append(of.ofp_action_output(port = prt))
          match = of.ofp_match.from_packet(packet, inport)
          match.dl_src = None # Wildcard source MAC

          msg = of.ofp_flow_mod(command=of.OFPFC_ADD,buffer_id=event.ofp.buffer_id,actions=actions,match=of.ofp_match.from_packet(packet,inport))
          event.connection.send(msg.pack())
          return
        else:
          if (dpid,dstaddr) not in self.message_queue:
            self.message_queue[(dpid,dstaddr)] = []
          bucket = self.message_queue[(dpid,dstaddr)]
          entry = (None,event.ofp.buffer_id,inport)
          bucket.append(entry)
		  
          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 = dstaddr
          r.hwsrc = dpid_to_mac(dpid)
          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" % (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
      log.debug("%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))
      
      dstaddr = a.protodst
      
      prt = None
      for list in self.routingTable[dpid]:
        if list[0] == str(dstaddr):
          log.debug("Searching Routing Table for IP address: %s ",str(dstaddr))
          prt = list[4]
          log.debug("The mac address is %s",dpid_to_mac(dpid))
        if list[3] == str(dstaddr):
          prt = list[4]
          #icmpflag = 1
          self.arpTable[dpid][dstaddr] = Entry(prt, dpid_to_mac(dpid)) 
          log.debug("The mac address is %s",dpid_to_mac(dpid))

      if prt == None:
        log.debug("Unreachable IP Address : %s",str(dstaddr))
        return
      
      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)
            log.debug("The inport %i The input  mac address is %s",inport,str(packet.src))

            # Send any waiting packets...
            self.sendWaitingPackets(dpid, a.protosrc, packet.src, inport)

            if a.opcode == arp.REQUEST:
              # Maybe we can answer

              if a.protodst in self.arpTable[dpid]:
                # We have an answer...
                  log.debug("This is a known path")
                  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.protodst = a.protosrc
                  r.protosrc = a.protodst
                  r.hwsrc = self.arpTable[dpid][a.protodst].mac
                  e = ethernet(type=packet.type, src=dpid_to_mac(dpid), dst=a.hwsrc)
                  e.set_payload(r)
                  log.debug("%i %i answering ARP from %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 =
                                                          of.OFPP_IN_PORT))
                  msg.in_port = inport
                  event.connection.send(msg)
                  return

            if a.opcode == arp.REPLY:
              self.arpTable[dpid][dstaddr] = Entry(prt, a.hwsrc)
              for list in self.routingTable[dpid]:
                if list[0] == str(a.protodst):
                  log.debug("Searching Routing Table for IP address: %s ",str(a.protodst))
                  prt = list[4]		
                  msg = of.ofp_packet_out(in_port = inport, action = of.ofp_action_output(port = prt))
                  

      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)))

      msg = of.ofp_packet_out(in_port = inport, action = of.ofp_action_output(port = of.OFPP_FLOOD))
      if event.ofp.buffer_id is of.NO_BUFFER:
        # Try sending the (probably incomplete) raw data
        msg.data = event.data
      else:
        msg.buffer_id = event.ofp.buffer_id
      event.connection.send(msg.pack())
Example #59
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)