From: Ian Jackson Date: Mon, 29 Sep 2014 14:17:13 +0000 (+0100) Subject: polypath: Provide Linux interface monitor X-Git-Tag: proposed.polypath.v4~19 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=secnet.git;a=commitdiff_plain;h=ed5d1eea357995d2c1e38b4ef3fffc7ebc891d8d 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 --- diff --git a/Makefile.in b/Makefile.in index 841a49b..f68022a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -30,11 +30,13 @@ RM:=@RM@ CC:=@CC@ INSTALL:=@INSTALL@ INSTALL_PROGRAM:=@INSTALL_PROGRAM@ +INSTALL_SCRIPT:=@INSTALL_SCRIPT@ prefix:=@prefix@ exec_prefix:=@exec_prefix@ sbindir:=@sbindir@ sysconfdir:=@sysconfdir@ +datarootdir:=@datarootdir@ transform:=@program_transform_name@ mandir:=@mandir@ @@ -47,7 +49,7 @@ CFLAGS:=-Wall @WRITESTRINGS@ @CFLAGS@ -Werror \ -Wno-strict-aliasing -fno-strict-aliasing \ -MMD 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) @@ -166,6 +168,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 \ @@ -179,6 +182,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..1b02bfa --- /dev/null +++ b/polypath-interface-monitor-linux @@ -0,0 +1,82 @@ +#!/usr/bin/perl -w +use strict; +use IO::Handle; + +my $us = $0; +$us =~ s{.*/}{}; + +die "$us: no arguments permitted\n" if @ARGV; + +our ($monh,$monchild); + +our %reported; +# no entry: not reported, does not exist +# /ry+/: reported, entry exists +# during processing only: +# /r/: reported, may not still exist +# /y+/: not reported, entry exists + +sub killmonitor () { + return unless $monchild; + kill 9, $monchild + or warn "$us: cannot kill monitor child [$monchild]: $!\n"; + $monchild=undef; + close $monh; +} + +END { killmonitor(); } + +my $restart; + +for (;;) { + my $o; + eval { + if (!$monh) { + killmonitor(); + $monh = new IO::File; + $monchild = 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; + } + $_='r' foreach values %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 = ''; + } + 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 27c3f46..3bd835e 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,