#!/usr/bin/ruby

## macfinder.rb v0.1 : Find mac Address in a pcap file.
## Copyright (C) 2009  Franck GUENICHOT
## franck {dot} guenichot {at} orange {dot} fr
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.

## Written for the Network Forensic Puzzle #3
## http://forensicscontest.com


require 'rubygems'
require 'packetfu'
require 'optparse'
require "rubygems"

$VERSION = "0.1"
$PROGNAME = "macfinder"

#################################################################################################

# handle command line args
$options = {}
opts = OptionParser.new do|opts|
  opts.banner = "
    #{$PROGNAME} version #{$VERSION} 
    Copyright (C) 2009 Franck GUENICHOT
    #{$PROGNAME} comes with ABSOLUTELY NO WARRANTY;
    This is free software, and you are welcome
    to redistribute it under certain conditions.
    (GPL v3)	
    
    Usage: #{$PROGNAME} [options] <pcap_file>"
    
  $options[:ipaddr] = nil
  opts.on( '-i <IP_ADDRESS>', '--ip', 'Display Mac address for the given IP address only (4-digit decimal dot notation form)' ) do|addr|
    $options[:ipaddr] = addr
  end

  opts.on( '-v', '--version', 'Display version information' ) do
    puts $VERSION
    exit
  end

  opts.on( '-h', '--help', 'Display this screen' ) do
    puts opts
    exit
  end
end




#parse command line args
opts.parse!

$filename = ARGV[ARGV.length-1]


# if no file in input => display help and exit
if $filename == nil
  puts opts
  exit(0)
end

unless File.exist?($filename)
  puts "File: #{$filename} does not exist."
  exit(0)
end



mac_ip_h = {}
pkt_array = PacketFu::Read.f2a(:file => $filename)

pkt_array.each { |pkt|
  packet = PacketFu::Packet.parse(pkt)
	if not mac_ip_h.has_key?(packet.ip_saddr)	
  	mac_ip_h[packet.ip_saddr] = [packet.eth_saddr]
	else
		mac_ip_h[packet.ip_saddr] << packet.eth_saddr unless mac_ip_h[packet.ip_saddr].include?(packet.eth_saddr)
	end
}

if $options[:ipaddr] =~ /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/
  if mac_ip_h.has_key?($options[:ipaddr])
		number_of_mac = mac_ip_h[$options[:ipaddr]].length	
		if number_of_mac > 1
			puts "Warning ! found %d Mac address for %s" % [number_of_mac, $options[:ipaddr]]
			mac_ip_h[$options[:ipaddr]].each { |mac|
    		puts "Mac Address: #{mac}"
			}
		else
			puts "Mac: %s" % [mac_ip_h[$options[:ipaddr]]]
		end
 else
    puts "No Mac address found for %s" % [$options[:ipaddr]]
 end

else
  puts "Listing all Mac Address found !"
  mac_ip_h.each {|ip, mac|
  puts "IP: %s | Mac: %s" % [ip, mac]
  }
end

#End of macfinder.rb
