From e1f5f4ef34244ba52daed1614bf219aefeaddc64 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 29 Sep 2014 15:17:13 +0100 Subject: [PATCH] polypath: Provide Linux interface monitor This script monitors the local network interfaces and prints output as interfaces and addresses appear and disappear. Install it in $(datarootdir). Provide $(datarootdir) to C code via a -D compiler flag. Provide the appropriate path as the default setting for `monitor-command' in the polypath module. Signed-off-by: Ian Jackson --- Makefile.in | 6 ++- polypath-interface-monitor-linux | 73 ++++++++++++++++++++++++++++++++ polypath.c | 4 ++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100755 polypath-interface-monitor-linux diff --git a/Makefile.in b/Makefile.in index 0e00d07..f61bac4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -35,6 +35,7 @@ prefix:=@prefix@ exec_prefix:=@exec_prefix@ sbindir:=@sbindir@ sysconfdir:=@sysconfdir@ +datarootdir:=@datarootdir@ transform:=@program_transform_name@ mandir:=@mandir@ @@ -46,7 +47,7 @@ CFLAGS:=-Wall @WRITESTRINGS@ @CFLAGS@ -Werror \ -Wswitch-enum -Wunused-variable -Wunused-function -Wbad-function-cast \ -Wno-strict-aliasing -fno-strict-aliasing ALL_CFLAGS:=@DEFS@ -I$(srcdir) -I. $(CFLAGS) $(EXTRA_CFLAGS) -CPPFLAGS:=@CPPFLAGS@ $(EXTRA_CPPFLAGS) +CPPFLAGS:=@CPPFLAGS@ -DDATAROOTDIR='"$(datarootdir)"' $(EXTRA_CPPFLAGS) LDFLAGS:=@LDFLAGS@ $(EXTRA_LDFLAGS) LDLIBS:=@LIBS@ $(EXTRA_LDLIBS) @@ -170,6 +171,7 @@ check-ipaddrset: ipaddrset-test.py ipaddrset.py ipaddrset-test.expected installdirs: $(INSTALL) -d $(prefix)/share/secnet $(sbindir) $(INSTALL) -d $(mandir)/man8 + $(INSTALL) -d $(datarootdir)/secnet install: installdirs set -e; ok=true; for f in $(STALE_PYTHON_FILES); do \ @@ -183,6 +185,8 @@ install: installdirs $(INSTALL_PROGRAM) secnet $(sbindir)/`echo secnet|sed '$(transform)'` $(INSTALL_PROGRAM) ${srcdir}/make-secnet-sites $(sbindir)/`echo make-secnet-sites|sed '$(transform)'` $(INSTALL) ${srcdir}/ipaddrset.py $(prefix)/share/secnet/ipaddrset.py + $(INSTALL_SCRIPT) ${srcdir}/polypath-interface-monitor-linux \ + $(datarootdir)/secnet/. $(INSTALL) secnet.8 $(mandir)/man8/secnet.8 install-force: diff --git a/polypath-interface-monitor-linux b/polypath-interface-monitor-linux new file mode 100755 index 0000000..e02a9dd --- /dev/null +++ b/polypath-interface-monitor-linux @@ -0,0 +1,73 @@ +#!/usr/bin/perl -w +use strict; +use IO::Handle; + +my $us = $0; +$us =~ s{.*/}{}; + +die "$us: no arguments permitted\n" if @ARGV; + +our $monh; +our %reported; +# no entry: not reported, does not exist +# ry+: reported, entry exists +# r: reported, may not still exist (during processing only) +# y+: not reported, entry exists + +my $restart; + +for (;;) { + my $o; + eval { + if (!$monh) { + $monh = new IO::File; + open $monh, "-|", qw(ip -o monitor addr) + or die "spawn monitor: $!\n"; + sleep(1) if $restart++; + } else { + my $discard; + my $got = sysread $monh, $discard, 4096; + die "read monitor: $!\n" unless defined $got; + die "monitor failed\n" unless $got; + } +#use Data::Dumper; +#print STDERR "entering", Dumper \%reported; + $_='r' foreach values %reported; +#print STDERR "cleaned", Dumper \%reported; + foreach my $ip (qw(4 6)) { + my $addrh = new IO::File; + open $addrh, "-|", qw(ip -o), "-$ip", qw(addr show) + or die "spawn addr $ip show: $!\n"; + my $afstr = $ip==4 ? 'inet' : $ip==6 ? 'inet6' : die; + while (<$addrh>) { + if (m{^\d+\:\s*(\S+)\s+$afstr\s+([0-9a-z.:]+)(?:/\d+)?\s}) { + my $outline = "$ip $1 $2"; + $reported{$outline} .= "y"; + } else { + chomp; + warn "unexpected output from addr $ip show: $_\n"; + } + } + my $r = close $addrh; + die "addr $ip show failed $!\n" unless $r; + $o = ''; + } +#print STDERR "acquired", Dumper \%reported; + foreach my $k (keys %reported) { + local $_ = $reported{$k}; + if (m/^r$/) { + $o .= "-$k\n"; + delete $reported{$k}; + } elsif (m/^y/) { + $o .= "+$k\n"; + } + } + }; + if ($@) { + print STDERR "$us: $@"; + sleep 5; + next; + } + print $o or die $!; + STDOUT->flush or die $!; +} diff --git a/polypath.c b/polypath.c index cdf82e2..9146c7a 100644 --- a/polypath.c +++ b/polypath.c @@ -43,7 +43,11 @@ static const char *const default_ifname_pats[] = { }; static const char *const default_monitor_command[] = { +#if __linux__ + DATAROOTDIR "/secnet/" "polypath-interface-monitor-linux", 0 +#else 0 +#endif }; static const char *polypath_addr_to_string(void *commst, -- 2.30.2