#!/usr/bin/env perl
#
# Copyright 2006-2011 Roy Hills
#
# This file is part of arp-scan.
# 
# arp-scan 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
# (at your option) any later version.
# 
# arp-scan 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 arp-scan.  If not, see <http://www.gnu.org/licenses/>.
#
# $Id: get-iab 18078 2011-01-09 10:37:07Z rsh $
#
# get-iab -- Fetch the IAB file from the IEEE website
#
# Author: Roy Hills
# Date: 16 March 2006
#
# This script downloads the Ethernet IAB file from the IEEE website, and
# converts it to the format needed by arp-scan.
#
# This script assumes that all the IAB entries start with 00-50-C2. This
# is currently the case, and will probably be so for the foreseeable
# future.
#
use warnings;
use strict;
use Getopt::Std;
use LWP::Simple;
#
my $default_url = 'http://standards.ieee.org/regauth/oui/iab.txt';
my $default_filename='ieee-iab.txt';
#
my $usage =
qq/Usage: get-iab [options]
Fetch the Ethernet IAB file from the IEEE website, and save it in the format
used by arp-scan.

'options' is one or more of:
        -h Display this usage message.
        -f FILE Specify the output IAB file. Default=$default_filename
        -u URL Specify the URL to fetch the IAB data from.
           Default=$default_url
        -v Give verbose progress messages.
/;
my %opts;
my $verbose;
my $filename;
my $url;
my $lineno = 0;
my $iab_var;
my $vendor;
#
# Process options
#
die "$usage\n" unless getopts('hf:v',\%opts);
if ($opts{h}) {
   print "$usage\n";
   exit(0);
}
if (defined $opts{f}) {
   $filename=$opts{f};
} else {
   $filename=$default_filename;
}
if (defined $opts{u}) {
   $url=$opts{u};
} else {
   $url=$default_url;
}
$verbose=$opts{v} ? 1 : 0;
#
# If the output filename already exists, rename it to filename.bak before
# we create the new output file.
#
if (-f $filename) {
   print "Renaming $filename to $filename.bak\n" if $verbose;
   rename $filename, "$filename.bak" || die "Could not rename $filename to $filename.bak\n";
}
#
# Fetch the content from the URL
#
print "Fetching IAB data from $url\n" if $verbose;
my $content = get $url;
die "Could not get IAB data from $url\n" unless defined $content;
my $content_length = length($content);
die "Zero-sized response from from $url\n" unless ($content_length > 0);
print "Fetched $content_length bytes\n" if $verbose;
#
# Open the output file for writing.
#
print "Opening output file $filename\n" if $verbose;
open OUTPUT, ">$filename" || die "Could not open $filename for writing";
#
# Write the header comments to the output file.
#
my ($sec,$min,$hour,$mday,$mon,$year,undef,undef,undef) = localtime();
$year += 1900;
$mon++;
my $date_string = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year, $mon, $mday,
                          $hour, $min, $sec);
my $header_comments =
qq/# ieee-iab.txt -- Ethernet vendor IAB file for arp-scan
#
# This file contains the Ethernet vendor IABs for arp-scan.  These are used
# to determine the vendor for a give Ethernet interface given the MAC address.
#
# Each line of this file contains an IAB-vendor mapping in the form:
#
# <IAB><TAB><Vendor>
#
# Where <IAB> is the first 36 bits of the MAC address in hex, and <Vendor>
# is the name of the vendor.
#
# Blank lines and lines beginning with "#" are ignored.
#
# This file was automatically generated by get-iab at $date_string
# using data from $url
#
# Do not edit this file.  If you want to add additional MAC-Vendor mappings,
# edit the file mac-vendor.txt instead.
#
/;
print OUTPUT $header_comments;
#
# Parse the content received from the URL, and write the IAB entries to the
# output file.  Match lines that look like this:
# 000000-000FFF   (base 16)       T.L.S. Corp.
# and write them to the output file looking like this:
# 0050C2000	T.L.S. Corp.
#
# Note that the 0050C2 bit is a constant, and we take
# the next three hex digits from the IEEE data.
#
while ($content =~ m/^(\w+)-\w+\s+\(base 16\)[ 	]+(.*)$/gm) {
   $iab_var = substr($1,0,3);
   $vendor = $2;
   $vendor = "PRIVATE" if length($vendor) == 0;
   print OUTPUT "0050C2$iab_var\t$vendor\n";
   $lineno++;
}
#
# All done.  Close the output file and print IAB entry count
#
close OUTPUT || die "Error closing output file\n";
print "$lineno IAB entries written to file $filename\n" if $verbose;
