ANTFARM/Traceroute/Traceroute script
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