Jump to content

ANTFARM/Traceroute/Traceroute script

From Wikibooks, open books for an open world

The purpose of this script is to simply parse through a traceroute file and extract information needed to feed into Antfarm's graphical view.

 #!/usr/bin/env ruby
 #
 # Copyright (2008) Sandia Corporation.
 # Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
 # the U.S. Government retains certain rights in this software.
 #
 # Original Author: Michael Berg, Sandia National Laboratories <mjberg@sandia.gov>
 # Modified By: Bryan T. Richardson, Sandia National Laboratories <btricha@sandia.gov>
 # Further Modifications By: Melissa Myerly & Cassandra Trevino, Sandia National Laboratories
 # This library is free software; you can redistribute it and/or modify it
 # under the terms of the GNU Lesser General Public License as published by
 # the Free Software Foundation; either version 2.1 of the License, or (at
 # your option) any later version.
 #
 # This library 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 Lesser General Public License for more
 # details.
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with this library; if not, write to the Free Software Foundation, Inc.,
 # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 #
 def parse(file)
 puts "Filename: "        #This is here for convenience, it simply prints the filename you are parsing to the screen.
 puts  file

Regular expressions are used to parse through the traceroute file. The items that are parsed out of the traceroute file are the hostname, time, hop count, and the ip address. The time or hop count items are not utilized in this script.

  hostname_regexp =       Regexp.new('(\S+)\.[a-z]*(\d)*')
  time_regexp =           Regexp.new('(<*\d+\s*ms\s*){1,3}')
  hop_regexp   =          Regexp.new('(\d){1,3}')
  ipv4_regexp =           Regexp.new('((\d){1,3}\.(\d){1,3}\.(\d){1,3}\.(\d){1,3})')

All items used to store data in the database are set to nil.

  hostname = nil
  source_addr = nil
  source_hostname = nil
  dest_addr = nil
  dest_hostname = nil
  list = File.open(file)
  firstline = list.gets()

For each line in the traceroute file, the records in the database are checked to ensure that the hostname or ip address don't already exist so that they could be added into the database. This is happening as each ip address and hostname are parsed from the traceroute file.

  source_addr = ipv4_regexp.match(firstline)
  source_hostname = hostname_regexp.match(firstline)
  list.each do |line|
   dest_addr = ipv4_regexp.match(line)
   dest_hostname = hostname_regexp.match(line)
   if dest_hostname
     if ipv4_regexp.match( "#{dest_hostname}" )
         dest_hostname = nil
     end
   end 
   source_iface = IpInterface.find_or_initialize_by_address("#{source_addr}")
                 if source_iface.new_record?
                   source_iface.node_name = "#{source_addr}"      #Assign the node name in the database to the source address
                   source_iface.node_device_type = 'TRACEROUTE'   #Informing the database this is from TRACEROUTE data 
                   source_iface.save false
                 end
                 dest_iface = IpInterface.find_or_initialize_by_address("#{dest_addr}")
                 if dest_iface.new_record?
                   dest_iface.node_name = "#{dest_addr}"
                   dest_iface.node_device_type = 'TRACEROUTE'
                   dest_iface.save false
                 end

The following is used to feed the information extracted from the traceroute file into the database. The source_iface.layer3_interface.id refers to the source address and the dest_iface.layer3_interface.id refers to the destination address.

   traffic = Traffic.first(:conditions => { :source_layer3_interface_id => source_iface.layer3_interface.id,
                                            :target_layer3_interface_id => dest_iface.layer3_interface.id })
  unless traffic
   traffic = Traffic.create :source_layer3_interface => source_iface.layer3_interface,
                            :target_layer3_interface => dest_iface.layer3_interface,
                            :description => "TRACEROUTE"
  end

The following 3 puts statements are not required, they are used for convenience and to verify that the correct hostnames and associated ip addresses are being placed in the correct table in the database.

   puts "Source Hostname Addr  #{source_hostname}  #{source_addr} "
   puts "Dest Hostname Addr  #{dest_hostname}  #{dest_addr}"
   puts "end of line"

The source address and hostname must become the destination address and hostname for the next iteration of the loop (and for the graphic produced by Antfarm to make sense).

    source_addr = dest_addr
    source_hostname = dest_hostname
   end
 end
 if ARGV[0] == '--help'
   #print_help
 else
   ARGV.each do |arg|
     if File.directory?(arg)
       Find.find(arg) do |path|
         if File.file?(path)
           parse(path)
         end
       end
     else
       parse(arg)
     end
   end
 end