netutils 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|