summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniil Baturin <daniil@baturin.org>2014-07-25 18:13:39 +0200
committerDaniil Baturin <daniil@baturin.org>2014-07-25 18:13:39 +0200
commit974a522ebd298aecb4f502bab89d76a4ddbec899 (patch)
tree50a782e13bb1529a4199b621ffbf9752200ef969
parente70d602929e3017dd2cbac99900f9d4c436d2a60 (diff)
downloadvyatta-cfg-system-974a522ebd298aecb4f502bab89d76a4ddbec899.tar.gz
vyatta-cfg-system-974a522ebd298aecb4f502bab89d76a4ddbec899.zip
Add vyod-intfwatchd for restoring IPv6 addresses after link flaps.
As bad as it can be, it seems to sort of work.
-rw-r--r--Makefile.am2
-rwxr-xr-xetc/init.d/vyos-intfwatchd87
-rw-r--r--scripts/vyos-intfwatchd159
3 files changed, 248 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index 35117ebc..7b6218eb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,6 +21,7 @@ checkparamsonreboot_DATA += scripts/check-params-on-reboot.d/README
initd_SCRIPTS += etc/init.d/ec2-fetch-ssh-public-key
initd_SCRIPTS += etc/init.d/vyatta-config-reboot-params
+initd_SCRIPTS += etc/init.d/vyos-intfwatchd
checkparamsonreboot_SCRIPTS += scripts/check-params-on-reboot.d/ipv6_disable_blacklist
@@ -76,6 +77,7 @@ sbin_SCRIPTS += scripts/vyatta-bridgegroup-depedency.pl
sbin_SCRIPTS += scripts/vyatta-dhcpv6-client.pl
sbin_SCRIPTS += scripts/vyatta-update-grub.pl
sbin_SCRIPTS += scripts/vyatta-encapsulation
+sbin_SCRIPTS += scripts/vyos-intfwatchd
sbin_PROGRAMS = src/valid_address
sbin_PROGRAMS += src/local_ip
diff --git a/etc/init.d/vyos-intfwatchd b/etc/init.d/vyos-intfwatchd
new file mode 100755
index 00000000..fd7216c6
--- /dev/null
+++ b/etc/init.d/vyos-intfwatchd
@@ -0,0 +1,87 @@
+#! /bin/sh
+
+### BEGIN INIT INFO
+# Provides: vyos-intfwatchd
+# Required-Start: $remote_fs $syslog
+# Required-Stop: $remote_fs $syslog
+# Default-Start: 2 3 4 5
+# Default-Stop:
+# Short-Description: Interface status monitoring daemon
+### END INIT INFO
+
+set -e
+
+# /etc/init.d/vyos-intfwatchd: start and stop the event watching daemon
+
+test -x /opt/vyatta/sbin/vyos-intfwatchd || exit 0
+
+umask 022
+
+. /lib/lsb/init-functions
+
+if [ -n "$2" ]; then
+ EWD_OPTS="$EWD_OPTS $2"
+fi
+
+# Are we running from init?
+run_by_init() {
+ ([ "$previous" ] && [ "$runlevel" ]) || [ "$runlevel" = S ]
+}
+
+check_dev_null() {
+ if [ ! -c /dev/null ]; then
+ if [ "$1" = log_end_msg ]; then
+ log_end_msg 1 || true
+ fi
+ if ! run_by_init; then
+ log_action_msg "/dev/null is not a character device!"
+ fi
+ exit 1
+ fi
+}
+
+export PATH="${PATH:+$PATH:}/usr/sbin:/sbin:/usr/bin:/opt/vyatta/sbin"
+
+case "$1" in
+ start)
+ check_dev_null
+ log_daemon_msg "Starting vyos-intfwatchd" "vyos-intfwatchd"
+ if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/vyos-intfwatchd.pid --exec /opt/vyatta/sbin/vyos-intfwatchd -- $EWD_OPTS; then
+ log_end_msg 0
+ else
+ log_end_msg 1
+ fi
+ ;;
+ stop)
+ log_daemon_msg "Stopping vyos-intfwatchd" "vyos-intfwatchd"
+ VI_PID=`cat /var/run/vyos-intfwatchd.pid`
+ for p in `pgrep -P $VI_PID`; do
+ kill $p
+ done
+ if start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/vyos-intfwatchd.pid; then
+ log_end_msg 0
+ else
+ log_end_msg 1
+ fi
+ ;;
+ restart)
+ log_daemon_msg "Restarting vyos-intfwatchd" "vyos-intfwatchd"
+ start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile /var/run/vyos-intfwatchd.pid
+ check_for_no_start log_end_msg
+ check_dev_null log_end_msg
+ if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/vyos-intfwatchd.pid --exec /opt/vyatta/sbin/vyos-intfwatchd -- $EWD_OPTS; then
+ log_end_msg 0
+ else
+ log_end_msg 1
+ fi
+ ;;
+ status)
+ status_of_proc -p /var/run/vyos-intfwatchd.pid /opt/vyatta/sbin/vyos-intfwatchd vyos-intfwatchd && exit 0 || exit $?
+ ;;
+
+ *)
+ log_action_msg "Usage: /etc/init.d/vyos-intfwatchd {start|stop|restart|status}"
+ exit 1
+esac
+
+exit 0
diff --git a/scripts/vyos-intfwatchd b/scripts/vyos-intfwatchd
new file mode 100644
index 00000000..8f9842c2
--- /dev/null
+++ b/scripts/vyos-intfwatchd
@@ -0,0 +1,159 @@
+#!/usr/bin/perl
+#
+# Module: vyos-restore-static-ipv6.pl
+#
+# **** License ****
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# Copyright (C) 2014 VyOS Development Group
+#
+# **** End License ****
+
+use lib "/opt/vyatta/share/perl5";
+use strict;
+use warnings;
+use POSIX;
+use Fcntl;
+use Sys::Syslog;
+use Vyatta::Config;
+use Vyatta::Interface;
+use Data::Dumper;
+
+use constant
+{
+ # Program settings
+ PROGRAM_NAME => "vyos-intfwatchd",
+ PROGRAM_VERSION => "1.0",
+ PID_FILE => "/var/run/vyos-intfwatchd.pid",
+
+ # Program exit codes
+ SUCCESS => 0,
+ ERROR => 1,
+
+ # Subroutine error codes
+ SUB_ERROR => 0,
+ SUB_SUCCESS => 1,
+
+ # Fcntl file lock/unlock constants
+ SET_EXCLUSIVE_LOCK => 2,
+ UNLOCK => 8
+};
+
+sub daemonize
+{
+ syslog("info", "%s", "Starting in daemon mode");
+
+ my $pid = fork();
+ if (!defined($pid))
+ {
+ # Fork failed
+ die "Could not spawn child process: $!, exiting";
+ }
+ elsif ($pid > 0)
+ {
+ # Child has been spawned succefully,
+ # parent should terminate now
+ exit(SUCCESS);
+ }
+ chdir("/");
+ umask(0);
+ setsid();
+
+ # Close standard i/o stream descriptors
+ open STDIN, "/dev/null" or die "Can't read /dev/null: $!";
+ open STDOUT, ">>/dev/null" or die "Can't write to /dev/null: $!";
+ open STDERR, ">>/dev/null" or die "Can't write to /dev/null: $!";
+}
+
+sub writePid
+{
+ my ($pid, $fh) = @_;
+
+ unless (flock($fh, SET_EXCLUSIVE_LOCK))
+ {
+ syslog("err", "%s", "Could not lock PID file: $!");
+ exit(ERROR);
+ }
+
+ print($fh $pid);
+}
+
+sub releasePid
+{
+ my $fh = shift;
+ flock($fh, UNLOCK);
+ close($fh);
+ unlink(PID_FILE);
+}
+
+
+daemonize();
+my $pidFile = PID_FILE;
+unless (open PID_HANDLE, ">$pidFile")
+{
+ syslog("err", "%s", "Could not create PID file: $!");
+ exit(1);
+}
+writePid($$, \*PID_HANDLE);
+
+my $config = new Vyatta::Config();
+
+my $ip_monitor = "ip monitor link";
+unless (open(HANDLE, "$ip_monitor|"))
+{
+ syslog("err", "%s", qq{Could not start IP monitor: $!\n});
+ exit(1);
+}
+
+sub terminate
+{
+ my $error = shift;
+ syslog("notice", "%s", PROGRAM_NAME." is terminating");
+ releasePid(\*PID_HANDLE);
+ exit(0);
+}
+
+$SIG{'INT'} = \&terminateNormally;
+$SIG{'TERM'} = \&terminateNormally;
+$SIG{'KILL'} = sub { exit(0); };
+
+# This solution should be bad enough to be fixed immediately
+# when feasible.
+
+while(<HANDLE>)
+{
+ if( $_ =~ /^[0-9]+:\s(.*)(@.*)\s<.*UP,.*>/ )
+ {
+ print "Event event $1\n";
+ my $intf_name = $1;
+ my $intf = new Vyatta::Interface($intf_name);
+ my $intf_addr_path = $intf->path() . " address";
+
+ # Get IPv6 addresses
+ my @addresses = grep /:/, $config->returnValues($intf_addr_path);
+ print Dumper(@addresses);
+
+ foreach my $address (@addresses)
+ {
+ system("ip address add $address dev $intf_name");
+ if( $? != 0 )
+ {
+ syslog("err", "%s", "Could not add address $address: $!");
+ }
+ else
+ {
+ syslog("notice", "%s", "Restoring address $address on interface $intf_name");
+ }
+ }
+
+ $intf = undef;
+ }
+}
+