netutils 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/README.md +36 -0
- data/Rakefile +6 -0
- data/bin/acl +109 -0
- data/bin/alaxala-deploy +271 -0
- data/bin/config-diff-check +111 -0
- data/bin/config-gets +64 -0
- data/bin/console +14 -0
- data/bin/host-locate-on-demand +102 -0
- data/bin/ipaddr-resolv +74 -0
- data/bin/ipaddr-resolv.sh +97 -0
- data/bin/mac-drop +84 -0
- data/bin/mac-nodrop +45 -0
- data/bin/port-shutdown +78 -0
- data/bin/setup +8 -0
- data/lib/netutils.rb +118 -0
- data/lib/netutils/arp.rb +28 -0
- data/lib/netutils/cli.rb +702 -0
- data/lib/netutils/cli/alaxala.rb +121 -0
- data/lib/netutils/cli/alaxala/interface.rb +137 -0
- data/lib/netutils/cli/alaxala/lldp.rb +166 -0
- data/lib/netutils/cli/alaxala/macfib.rb +62 -0
- data/lib/netutils/cli/alaxala/showarp.rb +51 -0
- data/lib/netutils/cli/alaxala/showroute.rb +86 -0
- data/lib/netutils/cli/alaxala/showvrf.rb +46 -0
- data/lib/netutils/cli/aruba.rb +15 -0
- data/lib/netutils/cli/cisco.rb +45 -0
- data/lib/netutils/cli/cisco/cdp.rb +117 -0
- data/lib/netutils/cli/cisco/ifsummary.rb +32 -0
- data/lib/netutils/cli/cisco/interface.rb +67 -0
- data/lib/netutils/cli/cisco/macfib.rb +38 -0
- data/lib/netutils/cli/cisco/showarp.rb +27 -0
- data/lib/netutils/cli/cisco/showinterface.rb +27 -0
- data/lib/netutils/cli/cisco/showroute.rb +73 -0
- data/lib/netutils/cli/cisco/showvrf.rb +45 -0
- data/lib/netutils/cli/nec.rb +20 -0
- data/lib/netutils/cli/nec/lldp.rb +16 -0
- data/lib/netutils/cli/paloalto.rb +21 -0
- data/lib/netutils/fsm.rb +43 -0
- data/lib/netutils/macaddr.rb +51 -0
- data/lib/netutils/oncequeue.rb +78 -0
- data/lib/netutils/parser.rb +30 -0
- data/lib/netutils/rib.rb +80 -0
- data/lib/netutils/switch.rb +402 -0
- data/lib/netutils/tunnel.rb +8 -0
- data/lib/netutils/version.rb +3 -0
- data/lib/netutils/vrf.rb +42 -0
- data/log/.gitignore +1 -0
- data/netutils.gemspec +33 -0
- metadata +195 -0
@@ -0,0 +1,111 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
dir=`dirname $0`/../../../conf/net
|
3
|
+
progname=`basename $0`
|
4
|
+
cd $dir
|
5
|
+
diffsep=
|
6
|
+
diffall=
|
7
|
+
tmpdira=a
|
8
|
+
tmpdirb=b
|
9
|
+
case `uname` in
|
10
|
+
Linux|*BSD*)
|
11
|
+
tmpdiropt='-p /tmp'
|
12
|
+
;;
|
13
|
+
*)
|
14
|
+
# Darwin does not have -p option...
|
15
|
+
;;
|
16
|
+
esac
|
17
|
+
tmpdir="`mktemp -u $tmpdiropt -d $progname.XXXXXXXX`"
|
18
|
+
#
|
19
|
+
usage()
|
20
|
+
{
|
21
|
+
echo "
|
22
|
+
Usage:
|
23
|
+
$progname -h
|
24
|
+
$progname [-d]
|
25
|
+
Description:
|
26
|
+
check to see if a configuration of a network switch generated
|
27
|
+
by \`\`config-gets'' and stored into $dir
|
28
|
+
is changed or not. Also, revert trivial modification such as
|
29
|
+
NTP drift, a timestamp of a configuration and so on.
|
30
|
+
Options:
|
31
|
+
-h: display this message.
|
32
|
+
-d: display detailed diff.
|
33
|
+
"
|
34
|
+
}
|
35
|
+
|
36
|
+
if [ ! -z "$1" -a ! "$1" = "-d" ]; then
|
37
|
+
usage
|
38
|
+
exit 1
|
39
|
+
fi
|
40
|
+
|
41
|
+
#
|
42
|
+
# filters to ignore a difference of a configuration of Cisco, Alaxala,
|
43
|
+
# Aruba WLC and NEC IX series even though no actual changes are made
|
44
|
+
# like below:
|
45
|
+
#
|
46
|
+
# Cisco:
|
47
|
+
# ! Last configuration change at 23:16:01 jst Sat Apr 14 2018 by hogehoge
|
48
|
+
# ! NVRAM config last updated at 00:28:45 jst Sun Apr 8 2018 by hogehoge
|
49
|
+
#
|
50
|
+
# Alaxala:
|
51
|
+
# #Last modified by hogehoge at Sun Apr 15 04:00:03 2018 JST with version 12.7.B
|
52
|
+
#
|
53
|
+
# NEC IX:
|
54
|
+
# ! Current time Apr 15-Sun-2018 02:11:02 JST
|
55
|
+
#
|
56
|
+
regexp=" \
|
57
|
+
-e ^ntp\sclock-period -e ^!\s(N|L|C) -e ^#L \
|
58
|
+
-e ^\s{3}key\s -e ^\s{3}ap-console-password\s \
|
59
|
+
-e ^\s{3}bkup-passwords\s -e ^\s{3}wpa-passphrase\s \
|
60
|
+
"
|
61
|
+
grep="grep -E $regexp"
|
62
|
+
grepex="grep -Ev $regexp"
|
63
|
+
#
|
64
|
+
if ! mkdir -p "$tmpdir/$tmpdira" "$tmpdir/$tmpdirb" > /dev/null 2>&1; then
|
65
|
+
echo "Cannot create temporary directory!!!"
|
66
|
+
exit 1
|
67
|
+
fi
|
68
|
+
for path in *.conf; do
|
69
|
+
file=`basename $path`
|
70
|
+
diff=`git diff "$file"`
|
71
|
+
|
72
|
+
# force to generate diff. for a untracked file.
|
73
|
+
if [ -z "$diff" ]; then
|
74
|
+
if git status "$file" | grep "$file" > /dev/null 2>&1; then
|
75
|
+
diff=`diff -wc /dev/null "$file"`
|
76
|
+
fi
|
77
|
+
fi
|
78
|
+
|
79
|
+
[ -z "$diff" ] && continue
|
80
|
+
|
81
|
+
#
|
82
|
+
# hack for Cisco and Aruba WLC that have different values,
|
83
|
+
# e.g., NTP drift or password hash values, in configuration
|
84
|
+
# output even though the configuration is never modified.
|
85
|
+
#
|
86
|
+
if $grep "$file" > /dev/null 2>&1; then
|
87
|
+
tmpfilea="$tmpdir/$tmpdira/$file"
|
88
|
+
tmpfileb="$tmpdir/$tmpdirb/$file"
|
89
|
+
git show HEAD:./$file | $grepex > "$tmpfilea"
|
90
|
+
$grepex "$file" > "$tmpfileb"
|
91
|
+
diff=`cd "$tmpdir" && \
|
92
|
+
diff -wc "$tmpdira/$file" "$tmpdirb/$file"`
|
93
|
+
if [ -z "$diff" ]; then
|
94
|
+
git checkout HEAD -- $file
|
95
|
+
continue
|
96
|
+
fi
|
97
|
+
fi
|
98
|
+
|
99
|
+
echo "$file changes"
|
100
|
+
diffall="$diffall$diffsep$diff"
|
101
|
+
diffsep="
|
102
|
+
"
|
103
|
+
done
|
104
|
+
rm -rf "$tmpdira" "$tmpdirb"
|
105
|
+
|
106
|
+
if [ -z "$diffall" ]; then
|
107
|
+
echo 'nothing changed.'
|
108
|
+
elif [ "$1" = '-d' ]; then
|
109
|
+
echo ''
|
110
|
+
echo "$diffall" | sed -re '/^[^ ]* +block-list \[ / s/\./[.]/g'
|
111
|
+
fi
|
data/bin/config-gets
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.join(File.expand_path(File.dirname(__FILE__)).untaint, '/..')
|
3
|
+
|
4
|
+
require 'netutils'
|
5
|
+
#
|
6
|
+
def usage(errmsg = nil)
|
7
|
+
progname = File.basename($0)
|
8
|
+
STDERR.print "ERROR: #{errmsg}\n\n" if errmsg
|
9
|
+
STDERR.print "\
|
10
|
+
Usage:
|
11
|
+
#{progname} -h
|
12
|
+
#{progname} [-a] <switch IP address1> <switch IP address2> ...
|
13
|
+
Description:
|
14
|
+
retrieve configurations of network switches. If an option, ``-a,''
|
15
|
+
is specified, retrieve from all neighboring switches as well using
|
16
|
+
LLDP or CDP.
|
17
|
+
Arguments:
|
18
|
+
switch IP address:
|
19
|
+
an IP address of a switch. If no IP address is given,
|
20
|
+
pre-defined IP addresses are used.
|
21
|
+
Options:
|
22
|
+
-h: output this help message.
|
23
|
+
-a: try to find all neighboring switches.
|
24
|
+
Example:
|
25
|
+
#{progname} 192.168.0.1
|
26
|
+
#{progname} -a 192.168.0.1
|
27
|
+
"
|
28
|
+
exit 1
|
29
|
+
end
|
30
|
+
|
31
|
+
if ARGV[0] === '-h'
|
32
|
+
ARGV.shift
|
33
|
+
usage
|
34
|
+
end
|
35
|
+
if ARGV[0] === '-a'
|
36
|
+
ARGV.shift
|
37
|
+
Switch.set_retrieve_all
|
38
|
+
end
|
39
|
+
if ARGV.length > 0
|
40
|
+
ARGV.each do |ia|
|
41
|
+
Switch.new(nil, Switch::Type::ROUTER, ia)
|
42
|
+
end
|
43
|
+
else
|
44
|
+
SWITCHES.each { |name, ia| Switch.new(name, Switch::Type::ROUTER, ia) }
|
45
|
+
end
|
46
|
+
|
47
|
+
Switch.retrieve do |sw|
|
48
|
+
start = Time.now
|
49
|
+
if sw.name
|
50
|
+
print "Connecting: ``#{sw.name}'' (#{sw.ia})\n"
|
51
|
+
else
|
52
|
+
print "Connecting: #{sw.ia}\n"
|
53
|
+
end
|
54
|
+
sw.login
|
55
|
+
duration = Time.now - start
|
56
|
+
print " Connected: ``#{sw.name}'' (#{sw.ia}) (#{sw.maker_to_s} #{sw.product}) (#{duration} seconds)\n"
|
57
|
+
sw.config_get
|
58
|
+
sw.config_dump(File.join(File.expand_path(File.dirname(__FILE__)).untaint, '/../../../conf/net'))
|
59
|
+
#switch.if_dump
|
60
|
+
#switch.if_dump_csv
|
61
|
+
print " Done: ``#{sw.name}'' (#{sw.ia}) (#{sw.maker_to_s} #{sw.product})\n"
|
62
|
+
end
|
63
|
+
Switch.warn
|
64
|
+
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "netutils"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.join(File.expand_path(File.dirname(__FILE__)).untaint, '/..')
|
3
|
+
|
4
|
+
require 'netutils'
|
5
|
+
|
6
|
+
################################################################################
|
7
|
+
def usage
|
8
|
+
STDERR.print "\
|
9
|
+
Usage: #{$progname} [-h] [-d] <host IP address>
|
10
|
+
Description:
|
11
|
+
this script also locates an edge switch and a port using LLDP and/or CDP
|
12
|
+
to which an specified host is connected.
|
13
|
+
this script firstly locates a router that directly connects to a specified
|
14
|
+
IP address of a host. this script then resolves a MAC address of the IP
|
15
|
+
address. this script finally locates the switch and the port.
|
16
|
+
Options:
|
17
|
+
-h: output this help message.
|
18
|
+
-d: locate a directly connected router only.
|
19
|
+
Bugs:
|
20
|
+
this script may fail to locate a host when the host is already detached
|
21
|
+
from a network or the host does not generate any traffic for a certain
|
22
|
+
duration.
|
23
|
+
Example:
|
24
|
+
#{$progname} 192.168.0.1
|
25
|
+
"
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
|
29
|
+
usage if ! ARGV.size.between?(1, 2)
|
30
|
+
case ARGV[0]
|
31
|
+
when '-h'
|
32
|
+
usage
|
33
|
+
when '-d'
|
34
|
+
ARGV.shift
|
35
|
+
connectedonly = true
|
36
|
+
end
|
37
|
+
usage if ARGV.size != 1
|
38
|
+
|
39
|
+
ia = ARGV[0]
|
40
|
+
usage if ia !~ /^[0-9\.]+$/
|
41
|
+
|
42
|
+
def host_locate(sw, interface, ma)
|
43
|
+
vlan = interface_name_vlan_id(interface)
|
44
|
+
return sw, interface if ! vlan
|
45
|
+
|
46
|
+
sws = {}
|
47
|
+
while true
|
48
|
+
log_without_newline "\t#{sw.name} (#{sw.ia}) "
|
49
|
+
ports = sw.mac_address_table_get(ma, vlan)
|
50
|
+
if ports.size === 0
|
51
|
+
raise "No FIB entry found for #{ma} " +
|
52
|
+
"on #{sw.name} (#{sw.ia})"
|
53
|
+
end
|
54
|
+
ports.each do |name, port|
|
55
|
+
next if sws.has_key?(sw.name)
|
56
|
+
sws[sw.name] = sw
|
57
|
+
|
58
|
+
log "#{port}"
|
59
|
+
|
60
|
+
ssw = static_neighbor_resolve(sw.name, port)
|
61
|
+
if ssw
|
62
|
+
sw = ssw
|
63
|
+
else
|
64
|
+
nsw = sw.neighbor_gets(port)
|
65
|
+
if ! nsw ||
|
66
|
+
(nsw.type != Switch::Type::ROUTER &&
|
67
|
+
nsw.type != Switch::Type::SWITCH)
|
68
|
+
return sw, port
|
69
|
+
end
|
70
|
+
if ! nsw.ia
|
71
|
+
raise "ERROR: #{nsw.name} found but " +
|
72
|
+
"no IP address!!!"
|
73
|
+
end
|
74
|
+
sw = nsw
|
75
|
+
end
|
76
|
+
sw.login
|
77
|
+
break
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
begin
|
83
|
+
log "locating directly connected router for #{ia}... "
|
84
|
+
sw, xia = router_locate(ia)
|
85
|
+
if ia == xia
|
86
|
+
log "\t\"#{sw.name}\" (#{sw.ia})"
|
87
|
+
else
|
88
|
+
log "\t\"department router\" (#{xia})"
|
89
|
+
end
|
90
|
+
|
91
|
+
exit 0 if connectedonly
|
92
|
+
|
93
|
+
log_without_newline "resolving MAC address for #{xia}... "
|
94
|
+
ma, vrf, interface = sw.macaddr_resolve(xia)
|
95
|
+
log "found"
|
96
|
+
log "\t#{xia} #{ma} on VRF \"#{vrf.name}\" #{interface}"
|
97
|
+
|
98
|
+
log "locating MAC address #{ma}..."
|
99
|
+
sw, port = host_locate(sw, interface, ma)
|
100
|
+
rescue => e
|
101
|
+
log " FAILED: #{e.to_s}"
|
102
|
+
end
|
data/bin/ipaddr-resolv
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'resolv'
|
4
|
+
|
5
|
+
DOMAINS = [
|
6
|
+
'officecdn.microsoft.com',
|
7
|
+
'officecdn.microsoft.com.edgesuite.net',
|
8
|
+
'ctldl.windowsupdate.com',
|
9
|
+
'niig4.ocsp.secomtrust.net',
|
10
|
+
'repo1.secomtrust.net',
|
11
|
+
'scrootca1.ocsp.secomtrust.net',
|
12
|
+
'scrootca2.ocsp.secomtrust.net',
|
13
|
+
'repository.secomtrust.net',
|
14
|
+
'ocsp.digicert.com'
|
15
|
+
]
|
16
|
+
|
17
|
+
MAXTTL = 3600
|
18
|
+
|
19
|
+
class Domain
|
20
|
+
def initialize(name)
|
21
|
+
@name = name
|
22
|
+
@ias = {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def update
|
26
|
+
expires = @ias
|
27
|
+
@ias = {}
|
28
|
+
|
29
|
+
resolv = Resolv::DNS.new
|
30
|
+
rs = resolv.getresources(@name, Resolv::DNS::Resource::IN::A)
|
31
|
+
|
32
|
+
minttl = MAXTTL
|
33
|
+
rs.each do |r|
|
34
|
+
key = r.address.to_s
|
35
|
+
@ias[key] = r
|
36
|
+
if expires.has_key?(key)
|
37
|
+
expires.delete(key)
|
38
|
+
puts "#{@name}: #{key} update!!!"
|
39
|
+
else
|
40
|
+
puts "#{@name}: #{key} new!!!"
|
41
|
+
end
|
42
|
+
if minttl > r.ttl
|
43
|
+
minttl = r.ttl
|
44
|
+
end
|
45
|
+
end
|
46
|
+
expires.each do |k, v|
|
47
|
+
puts "#{@name}: #{v.address} expires!!!"
|
48
|
+
end
|
49
|
+
return minttl
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
domains = []
|
54
|
+
DOMAINS.each do |h|
|
55
|
+
domains <<= Domain.new(h)
|
56
|
+
end
|
57
|
+
|
58
|
+
while true
|
59
|
+
minttl = MAXTTL
|
60
|
+
domains.each do |d|
|
61
|
+
begin
|
62
|
+
ttl = d.update
|
63
|
+
rescue
|
64
|
+
ttl = 1
|
65
|
+
end
|
66
|
+
if minttl > ttl
|
67
|
+
minttl = ttl
|
68
|
+
end
|
69
|
+
end
|
70
|
+
if minttl < 1
|
71
|
+
minttl = 1
|
72
|
+
end
|
73
|
+
sleep minttl
|
74
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
hostnames="\
|
4
|
+
officecdn.microsoft.com \
|
5
|
+
officecdn.microsoft.com.edgesuite.net \
|
6
|
+
ctldl.windowsupdate.com \
|
7
|
+
niig4.ocsp.secomtrust.net \
|
8
|
+
repo1.secomtrust.net \
|
9
|
+
scrootca2.ocsp.secomtrust.net \
|
10
|
+
repository.secomtrust.net \
|
11
|
+
wpad.tottori-u.ac.jp \
|
12
|
+
"
|
13
|
+
filename=ipaddrs.txt
|
14
|
+
|
15
|
+
#
|
16
|
+
tmpfile=$filname.tmp
|
17
|
+
interval=300
|
18
|
+
expiry=864000
|
19
|
+
|
20
|
+
log()
|
21
|
+
{
|
22
|
+
|
23
|
+
echo `date '+%Y/%m/%d %H:%M:%S'` "$1"
|
24
|
+
}
|
25
|
+
|
26
|
+
resolve()
|
27
|
+
{
|
28
|
+
hostname=$1
|
29
|
+
|
30
|
+
host $hostname | sed -rn 's/^.* has address ([0-9.]+)$/\1/p'
|
31
|
+
}
|
32
|
+
|
33
|
+
add()
|
34
|
+
{
|
35
|
+
ia=$1
|
36
|
+
hostname=$2
|
37
|
+
time=$3
|
38
|
+
|
39
|
+
if ! remove $ia $hostname 'no'; then
|
40
|
+
log "add $hostname ($ia) $time"
|
41
|
+
r=0
|
42
|
+
else
|
43
|
+
r=1
|
44
|
+
fi
|
45
|
+
echo "$ia $hostname $time" >> $filename
|
46
|
+
return $r
|
47
|
+
}
|
48
|
+
|
49
|
+
remove()
|
50
|
+
{
|
51
|
+
ia=$1
|
52
|
+
hostname=$2
|
53
|
+
removeonly=$3
|
54
|
+
|
55
|
+
[ ! -e $filename ] && return
|
56
|
+
if [ "$removeonly" = 'yes' ]; then
|
57
|
+
log "Remove $hostname ($ia)"
|
58
|
+
fi
|
59
|
+
grep "^$ia .*$" $filename > /dev/null 2>&1
|
60
|
+
r=$?
|
61
|
+
if [ $r -eq 0 ]; then
|
62
|
+
grep -v "^$ia .*$" $filename > $tmpfile
|
63
|
+
mv $tmpfile $filename
|
64
|
+
fi
|
65
|
+
return $r
|
66
|
+
}
|
67
|
+
|
68
|
+
expire()
|
69
|
+
{
|
70
|
+
now=$1
|
71
|
+
expiry=$2
|
72
|
+
|
73
|
+
while read ia hostname lasttime; do
|
74
|
+
diff=`expr $now - $lasttime`
|
75
|
+
if [ $diff -gt $expiry ]; then
|
76
|
+
remove $ia $hostname 'yes'
|
77
|
+
fi
|
78
|
+
done < $filename
|
79
|
+
}
|
80
|
+
|
81
|
+
log 'Started'
|
82
|
+
while true; do
|
83
|
+
changed=no
|
84
|
+
now=`date +%s`
|
85
|
+
for h in $hostnames; do
|
86
|
+
for ia in `resolve $h`; do
|
87
|
+
if add "$ia" "$h" "$now"; then
|
88
|
+
changed=yes
|
89
|
+
fi
|
90
|
+
done
|
91
|
+
done
|
92
|
+
expire $now $expiry
|
93
|
+
if [ "$changed" = 'yes' ]; then
|
94
|
+
ruby wiredlanauth-filter-sync.rb
|
95
|
+
fi
|
96
|
+
sleep $interval
|
97
|
+
done
|