#!/usr/bin/env python2

"""of-switch.py: Impersonates an Openflow-based switch"""

__author__ = "Gregory Pickett"
__dated__ = "3/19/2014"
__copyright__ = "Copyright 2014, SDN Toolkit"

__license__ = "GNU General Public License version 3.0 (GPLv3)"
__version__ = "1.0.0"
__maintainer__ = "Gregory Pickett"
__email__ = "gregory.pickett@hellfiresecurity.com"
__twitter__ = "@shogun7273"
__status__ = "Production"

# Socket object needed
import socket

# Import fileinput to load addresses
import fileinput

# Import Argparse for command-line arguments
import argparse

# Header parsing object needed
import struct

# Packet builder object needed
import dpkt

# The format of the header on all OpenFlow packets.
OFP_HEADER_FORMAT = '!BBHL'
OFP_HEADER_LENGTH = 8

# The version code for the OpenFlow Protocol version 1.0.0.
OFP_VERSION_1_0_0 = 0x01

# OpenFlow message types.
# Immutable messages.
OFPT_HELLO = 0 # Symmetric message.
OFPT_ERROR = 1 # Symmetric message.
OFPT_ECHO_REQUEST = 2 # Symmetric message.
OFPT_ECHO_REPLY = 3 # Symmetric message.
OFPT_VENDOR = 4 # Symmetric message.
# Switch configuration messages.
OFPT_FEATURES_REQUEST = 5 # Controller/switch message.
OFPT_FEATURES_REPLY = 6 # Controller/switch message.
OFPT_GET_CONFIG_REQUEST = 7 # Controller/switch message.
OFPT_GET_CONFIG_REPLY = 8 # Controller/switch message.
OFPT_SET_CONFIG = 9 # Controller/switch message.
# Asynchronous messages.
OFPT_PACKET_IN = 10 # Async message.
OFPT_FLOW_REMOVED = 11 # Async message.
OFPT_PORT_STATUS = 12 # Async message.
# Controller command messages.
OFPT_PACKET_OUT = 13 # Controller/switch message.
OFPT_FLOW_MOD = 14 # Controller/switch message.
OFPT_PORT_MOD = 15 # Controller/switch message.
# Statistics messages.
OFPT_STATS_REQUEST = 16 # Controller/switch message.
OFPT_STATS_REPLY = 17 # Controller/switch message.
# Barrier messages.
OFPT_BARRIER_REQUEST = 18 # Controller/switch message.
OFPT_BARRIER_REPLY = 19 # Controller/switch message.
# Queue Configuration messages.
OFPT_QUEUE_GET_CONFIG_REQUEST = 20 # Controller/switch message.
OFPT_QUEUE_GET_CONFIG_REPLY = 21 # Controller/switch message.

# OFPT_FLOW_MOD message commands.
OFPFC_ADD = 0
OFPFC_MODIFY = 1
OFPFC_MODIFY_STRICT = 2
OFPFC_DELETE = 3
OFPFC_DELETE_STRICT = 4

# Process command-line arguments
argParser = argparse.ArgumentParser(description='Impersonates an Openflow-based switch')
argParser.add_argument('--version', '-v', action='version', version='%(prog)s is at version 1.0.0')
argParser.add_argument('ip', type=str, help='Address of the controller')
argParser.add_argument('-p','--port', default=6633,type=int, help='Openflow port')
arguments = argParser.parse_args()

if arguments.ip != None:

	# Assign target controller
	ip = arguments.ip
	
	#
	try:
		client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		client_socket.connect((ip, arguments.port))	

		# Build Hello
		type = OFPT_HELLO
		length = OFP_HEADER_LENGTH
		xid = 0
		header = struct.pack(OFP_HEADER_FORMAT, OFP_VERSION_1_0_0, type, length, xid)
		client_socket.send(header)

		while(True):
		
			# Listen for response ...
			data = client_socket.recv(512)

			#
			version, msg_type, msg_length, xid = struct.unpack(OFP_HEADER_FORMAT, data[:8])

			#
			if msg_type == OFPT_HELLO:
				
				# Acknowledge Hello Exchange
				print('Hello\'s Exchanged')
				
				# Change state
				
				state = OFPT_HELLO
				
				
			elif msg_type == OFPT_FEATURES_REQUEST:
			
				# Only if Hello Exchange complete
				if state == OFPT_HELLO:

					# Acknowledge Features Request
					print('Received Feature Request')
				
					# Reply with bogus features from Openvswitch
					type = OFPT_FEATURES_REPLY
					length = 128
					xid = 0
					data = '\x00\x00\x00\x0c\x29\x55\xde\x2b\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x87\x00\x00\x0f\xff\xff\xfe\x00\x0c\x29\x55\xde\x2b\x62\x72\x2d\x69\x6e\x74\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x0c\x29\x55\xde\x2b\x65\x74\x68\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
					header = struct.pack(OFP_HEADER_FORMAT, OFP_VERSION_1_0_0, type, length, xid)
					client_socket.send(header+data)

					# Acknowledge Features Sent
					print('Sent Feature Reply')
					
				else:
				
					#
					pass
			
			elif msg_type == OFPT_SET_CONFIG:
			
				# Only if Hello Exchange complete
				if state == OFPT_HELLO:
				
					# Acknowledge Config Set
					print('Received Config Set')
				
					# Record configuration
					config, max = struct.unpack("HH", data[8:12])
				
				else:
				
					#
					pass
			
			elif msg_type == OFPT_GET_CONFIG_REQUEST:
			
				# Only if Hello Exchange complete
				if state == OFPT_HELLO:

					# Acknowledge Config Request
					print('Received Config Request')
				
					# Mirror configuration
					type = OFPT_GET_CONFIG_REPLY
					length = 12
					xid = 0
					data = struct.pack('!HH', config, max)
					header = struct.pack(OFP_HEADER_FORMAT, OFP_VERSION_1_0_0, type, length, xid)
					client_socket.send(header+data)					

					# Acknowledge Config Reply
					print('Sent Config Reply')

					# OFPT_GET_CONFIG_REPLY response time slow ... Missing OFPT_STATS_REQUEST
					# Sending bogus stats from Openvswitch
					type = OFPT_STATS_REPLY
					length = 1068
					xid = 0
					data = '\x00\x00\x00\x00\x4e\x69\x63\x69\x72\x61\x20\x4e\x65\x74\x77\x6f\x72\x6b\x73\x2c\x20\x49\x6e\x63\x2e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4f\x70\x65\x6e\x20\x76\x53\x77\x69\x74\x63\x68\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x31\x2e\x32\x2e\x30\x2b\x62\x75\x69\x6c\x64\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4e\x6f\x6e\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4e\x6f\x6e\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
					header = struct.pack(OFP_HEADER_FORMAT, OFP_VERSION_1_0_0, type, length, xid)
					client_socket.send(header+data)			

					# Acknowledge Stats Reply
					print('Sent Stats Reply')	
					
				else:
				
					#
					pass
			
			elif msg_type == OFPT_STATS_REQUEST:
			
				# Only if Hello Exchange complete
				if state == OFPT_HELLO:

					# Acknowledge Stats Request
					print('Received Stats Request')				
				
					# Reply with bogus stats from Openvswitch
					type = OFPT_STATS_REPLY
					length = 1068
					xid = 0
					data = '\x00\x00\x00\x00\x4e\x69\x63\x69\x72\x61\x20\x4e\x65\x74\x77\x6f\x72\x6b\x73\x2c\x20\x49\x6e\x63\x2e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4f\x70\x65\x6e\x20\x76\x53\x77\x69\x74\x63\x68\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x31\x2e\x32\x2e\x30\x2b\x62\x75\x69\x6c\x64\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4e\x6f\x6e\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4e\x6f\x6e\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
					header = struct.pack(OFP_HEADER_FORMAT, OFP_VERSION_1_0_0, type, length, xid)
					client_socket.send(header+data)			

					# Acknowledge Stats Reply
					print('Sent Stats Reply')	
					
				else:
				
					#
					pass
			
			elif msg_type == OFPT_ECHO_REQUEST:
			
				# Only if Hello Exchange complete
				if state == OFPT_HELLO:

					# Acknowledge Echo Request
					print('Received Echo Request')	
				
					# Send Reply
					type = OFPT_ECHO_REPLY
					length = OFP_HEADER_LENGTH
					xid = 8
					header = struct.pack(OFP_HEADER_FORMAT, OFP_VERSION_1_0_0, type, length, xid)
					client_socket.send(header)					

					# Acknowledge Echo Reply
					print('Sent Echo Reply')	
					
				else:
				
					#
					pass
			
			elif msg_type == OFPT_FLOW_MOD:
			
				# Only if Hello Exchange complete
				if state == OFPT_HELLO:

					# Process Flow Modification
					wildcards, in_port, dl_src, dl_dst, dl_vlan, dl_vlan_pcp, dl_type, nw_tos, nw_proto, nw_src, nw_dst, tp_src, tp_dst = struct.unpack('!LH6s6sHBxHBB2x4s4sHH', data[8:48])
					cookie, command, idle_timeout, hard_timeout, priority, buffer_id, out_port, flags = struct.unpack('!QHHHHLHH', data[48:72])
				
					# Translate command
					if command == OFPFC_ADD:
					
						verb = "Add"
					
					elif command == OFPFC_MODIFY:
					
						verb = "Modify"
					
					elif command == OFPFC_MODIFY_STRICT:
					
						verb = "Modify"
					
					elif command == OFPFC_DELETE:
					
						verb = "Delete"
					
					elif command == OFPFC_DELETE_STRICT:				
					
						verb = "Delete"
					
					# Display Flow Modification
					print('Flow Modification : %s flow for protocol %i from port %i to port %i' % (verb, nw_proto, tp_src, tp_dst) )

				else:

					#
					pass
			
			elif msg_type == OFPT_PACKET_OUT:
			
				# Only if Hello Exchange complete
				if state == OFPT_HELLO:

					# Process Packet Out
					buffer_id, in_port, actions_len = struct.unpack('!LHH', data[8:16])
					action_type = struct.unpack('!H', data[16:18])
					pkt_start = OFP_HEADER_LENGTH + 8 + actions_len
					
					if length > (pkt_start):
					
						eth = dpkt.ethernet.Ethernet(data[pkt_start:length])
						
						if eth.type == dpkt.ethernet.ETH_TYPE_IP:

							ip = eth.data

							if ip.p == dpkt.ip.IP_PROTO_TCP:

								# Display TCP Packet Out					
								tcp = ip.data
								print('Packet Out (TCP) for %s:%i from %s:%i' % (ip.src, ip.dst, tcp.sport, tcp.dport))
							
							elif ip.p == dpkt.ip.IP_PROTO_UDP:
							
								# Display UDP Packet Out
								udp = ip.data
								print('Packet Out (UDP) for %s:%i from %s:%i' % (ip.src, ip.dst, udp.sport, udp.dport))						
							
							else:
							
								# Display Other Packet Out
								print('Packet Out (Other IP-Based Protocol) for %s from %s' % (ip.src, ip.dst))
							
						else:
					
							# Display Non-IP Packet Out
							print('Packet Out (%x Protocol)' % eth.type)

					else:
					
						# Display Empty Packet Out
						print('Packet Out (Empty)')
						
				else:
				
					#
					pass
			
			elif msg_type == OFPT_ECHO_REPLY:
			
				# Only if Hello Exchange complete
				if state == OFPT_HELLO:

					# Acknowledge Echo Reply
					print('Received Echo Reply')
					
				else:

					#
					pass
			
			else:
			
				#  
				pass

	except socket.timeout:
		
		# Acknowledge timeout
		print('Timeout!')
		
	except socket.error:
	
		# Acknowledge error
		print('Error!')