Commit | Line | Data |
---|---|---|
e61a41a4 IJ |
1 | #!/usr/bin/perl -w |
2 | use strict; | |
3 | use IO::Handle; | |
4 | ||
5 | my $us = $0; | |
6 | $us =~ s{.*/}{}; | |
7 | ||
8 | die "$us: no arguments permitted\n" if @ARGV; | |
9 | ||
10 | our ($monh,$monchild); | |
11 | ||
12 | our %reported; | |
13 | # no entry: not reported, does not exist | |
14 | # /ry+/: reported, entry exists | |
15 | # during processing only: | |
16 | # /r/: reported, may not still exist | |
17 | # /y+/: not reported, entry exists | |
18 | ||
19 | sub killmonitor () { | |
20 | return unless $monchild; | |
21 | kill 9, $monchild | |
22 | or warn "$us: cannot kill monitor child [$monchild]: $!\n"; | |
23 | $monchild=undef; | |
24 | close $monh; | |
25 | } | |
26 | ||
27 | END { killmonitor(); } | |
28 | ||
29 | my $restart; | |
30 | ||
31 | for (;;) { | |
32 | my $o; | |
33 | eval { | |
34 | if (!$monh) { | |
35 | killmonitor(); | |
36 | $monh = new IO::File; | |
37 | $monchild = open $monh, "-|", qw(ip -o monitor addr) | |
38 | or die "spawn monitor: $!\n"; | |
39 | sleep(1) if $restart++; | |
40 | } else { | |
41 | my $discard; | |
42 | my $got = sysread $monh, $discard, 4096; | |
43 | die "read monitor: $!\n" unless defined $got; | |
44 | die "monitor failed\n" unless $got; | |
45 | } | |
46 | $_='r' foreach values %reported; | |
47 | foreach my $ip (qw(4 6)) { | |
48 | my $addrh = new IO::File; | |
49 | open $addrh, "-|", qw(ip -o), "-$ip", qw(addr show) | |
50 | or die "spawn addr $ip show: $!\n"; | |
51 | my $afstr = $ip==4 ? 'inet' : $ip==6 ? 'inet6' : die; | |
52 | while (<$addrh>) { | |
53 | if (m{^\d+\:\s*(\S+)\s+$afstr\s+([0-9a-z.:]+)(?:/\d+)?\s}) { | |
54 | my $outline = "$ip $1 $2"; | |
55 | $reported{$outline} .= "y"; | |
56 | } else { | |
57 | chomp; | |
58 | warn "unexpected output from addr $ip show: $_\n"; | |
59 | } | |
60 | } | |
61 | my $r = close $addrh; | |
62 | die "addr $ip show failed $!\n" unless $r; | |
63 | $o = ''; | |
64 | } | |
65 | foreach my $k (keys %reported) { | |
66 | local $_ = $reported{$k}; | |
67 | if (m/^r$/) { | |
68 | $o .= "-$k\n"; | |
69 | delete $reported{$k}; | |
70 | } elsif (m/^y/) { | |
71 | $o .= "+$k\n"; | |
72 | } | |
73 | } | |
74 | }; | |
75 | if ($@) { | |
76 | print STDERR "$us: $@"; | |
77 | sleep 5; | |
78 | next; | |
79 | } | |
80 | print $o or die $!; | |
81 | STDOUT->flush or die $!; | |
82 | } |