module Msf

###
#
# This module provides methods for receiving raw packets. 
# Please see the ruby-pcapx documentation for more information.
#
###

module Exploit::Capture

	#
	# Initializes an instance of an exploit module that captures traffic
	#
	
	def initialize(info = {})
		super

		register_options(
			[
				OptString.new('INTERFACE', [false, 'The name of the interface']),
				OptString.new('FILTER', [false, 'The filter string for capturing traffic']),
				OptInt.new('SNAPLEN', [true, 'The number of bytes to capture', 65535])

			], Msf::Exploit::Capture
		)

		
		begin
			require 'PcapX'
			@pcapx_loaded = true
		rescue ::Exception => e
			@pcapx_loaded = false
			@pcapx_error  = e
		end
	
	end

	def stats_recv
		return(0) if not self.capture
		self.capture.stats.recv
	end

	def stats_drop
		return(0) if not self.capture
		self.capture.stats.drop
	end

	#
	# Opens a handle to the specified device
	#
	def open_pcap
	
		if (not @pcapx_loaded)
			print_status("The PcapX module is not available: #{@pcapx_error.to_s}")
			raise RuntimeError, "PcapX not available"
		end
		
		# XXX: Force the interface to be up
		system("ifconfig", datastore['INTERFACE'], "up")
	
		# Capture device
		dev = datastore['INTERFACE'] || ::PcapX.lookupdev
		len = datastore['SNAPLEN']   || 65535
		fil = datastore['FILTER']

		self.capture = ::PcapX::Capture.open_live(dev, len, true)

		if (not self.capture)
			raise RuntimeError, "Could not open the wireless device interface"
		end

		self.capture.setfilter(fil) if fil
	end

	def close_pcap 
		return if not self.capture
		self.capture.close
		self.capture = nil
	end

	def capture_find_linklayer(pkt)
		return if not pkt
		raw = pkt.raw_data
		off = 0

		case pkt.datalink
		when 119
			off = 144
		else
		end

		raw[off, raw.length - off]
	end

	def capture_extract_ies(raw)
		set = {}
		ret = 0
		idx = 0
		len = 0

		while (idx < raw.length)
			len = raw[idx+1]
			return set if not len
			set[ raw[idx] ] ||= []
			set[ raw[idx] ].push(raw[idx + 2, len])
			idx += len + 2
		end

		return set
	end

	attr_accessor :capture

end

end
