diff options
author | Daniil Baturin <daniil@baturin.org> | 2014-07-25 18:13:39 +0200 |
---|---|---|
committer | Daniil Baturin <daniil@baturin.org> | 2014-07-25 18:13:39 +0200 |
commit | 974a522ebd298aecb4f502bab89d76a4ddbec899 (patch) | |
tree | 50a782e13bb1529a4199b621ffbf9752200ef969 | |
parent | e70d602929e3017dd2cbac99900f9d4c436d2a60 (diff) | |
download | vyatta-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.am | 2 | ||||
-rwxr-xr-x | etc/init.d/vyos-intfwatchd | 87 | ||||
-rw-r--r-- | scripts/vyos-intfwatchd | 159 |
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; + } +} + |