First check in - not complete! The ifup script is functional though.

This commit is contained in:
2017-05-04 21:55:18 -05:00
commit b8d5489de6
6 changed files with 1176 additions and 0 deletions

75
Makefile Normal file
View File

@@ -0,0 +1,75 @@
# This file 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 here:
# (http://www.gnu.org/licenses/gpl-2.0.html)
#
# 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.
DEPENDS = iproute2,perl
ARCH =
URL =
BRIEF =
DESC =
SNAPVER =
ARCHIVE := $(PWD)/SRC/$(shell ls SRC|egrep '(bz2|gz|tar|xz)$$'|tail -1)
TYPE := $(shell file -ib $(ARCHIVE)|cut -d';' -f1|tr -d '\n')
SRCDIR := $(shell tar -tf $(ARCHIVE)|head -1|sed 's/\/.*//')
PATCHDIR := $(PWD)/SRC/patches
VERSION := $(shell echo $(SRCDIR)|egrep -o '\-[0-9].*'|sed 's/^-//')-$(SNAPVER)
include /usr/share/snap/Makefile.snaplinux
$(SRCDIR)/configure: $(ARCHIVE)
@if [ '$(TYPE)' == 'application/x-bzip2' ]; then \
tar -jxf $(ARCHIVE); \
elif [ '$(TYPE)' == 'application/x-gzip' ]; then \
tar -zxf $(ARCHIVE); \
elif [ '$(TYPE)' == 'application/x-tar' ]; then \
tar -xf $(ARCHIVE); \
elif [ '$(TYPE)' == 'application/x-xz' ]; then \
tar -xf $(ARCHIVE); \
else \
echo 'Unable to determine archive type'; \
exit 1; \
fi
@touch $(SRCDIR)/configure
$(SRCDIR)/config.log: $(SRCDIR)/configure
@cd $(SRCDIR) && \
for patch in `find $(PATCHDIR) -name \*.patch|sort`; do \
patch --verbose -Np1 -i $$patch; \
done
@cd $(SRCDIR); \
./configure \
--prefix=/usr \
--build=x86_64-snap-linux-gnu \
--host=x86_64-snap-linux-gnu \
--target=x86_64-snap-linux-gnu
$(SRCDIR)/binfile: $(SRCDIR)/config.log
@cd $(SRCDIR) && make
$(ROOT): $(SRCDIR)/binfile
@if [ -d $(ROOT) ]; then \
touch $(ROOT); \
else \
mkdir -v $(ROOT); \
fi
@cd $(SRCDIR) && make install DESTDIR=$(ROOT)
test: $(ROOT)
@cd $(SRCDIR); \
make check
clean:
@rm -rvf $(ROOT) \
$(SNAPINFO) \
$(MANIFEST) \
$(FILES) \
$(SRCDIR)

5
SNAP/README Normal file
View File

@@ -0,0 +1,5 @@
This is the directory where the manifest, snapinfo,
and files.tar.gz files will be created. It is also
where the usher file should be placed if it is
required by the package. Any other files that need
to be included could also be placed here.

906
SRC/ifup Executable file
View File

@@ -0,0 +1,906 @@
#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open3;
use IO::Select;
use Fcntl qw( LOCK_EX LOCK_NB );
use Data::Dumper;
open( SELF, "<$0" ) || error( int( $! ), "open(): $0: $!" );
flock( SELF, LOCK_EX|LOCK_NB ) || error( -1, "Another instance is running" );
use constant CONFDIR => '/etc';
use constant CONFIGFILE => CONFDIR . '/network.conf';
use constant NOACT => eval {
for ( my $i = 0; $i <= $#ARGV; $i++ ) {
if ( $ARGV[$i] eq '-n' || $ARGV[$i] eq '--no-act' ) {
splice( @ARGV, $i, 1 );
return( 1 );
}
}
return( 0 );
};
use constant VERBOSE => eval {
for ( my $i = 0; $i <= $#ARGV; $i++ ) {
if ( $ARGV[$i] eq '-v' || $ARGV[$i] eq '--verbose' ) {
splice( @ARGV, $i, 1 );
return( 1 );
}
}
return( 0 );
};
use constant VERSION => '0.1';
sub aliasdown {
my $alias = shift;
my $runningconf = shift;
my $aliases = $runningconf->{$alias->{'dev'}}{'aliases'};
my $result;
if ( my $running = $aliases->{$alias->{'name'}} ) {
if ( VERBOSE ) {
print "Deleting $running->{'address'}"
. " from $alias->{'dev'}"
. " (label $alias->{'dev'}:"
. "$alias->{'name'})\n";
}
$result = runcmd( "ip address delete"
. " $running->{'address'}"
. " dev $running->{'dev'} label"
. " $running->{'dev'}:$alias->{'name'}" );
if ( VERBOSE ) {
if ( $result->{'stdout'} ) {
print $result->{'stdout'};
}
if ( $result->{'stderr'} ) {
print STDERR $result->{'stderr'};
}
}
return( $result->{'stat'} );
}
}
sub aliasup {
my $alias = shift;
my $runningconf = shift;
my $dev = $alias->{'dev'};
my $name = $alias->{'name'};
my $result;
if ( my $old = $runningconf->{$dev}{'aliases'}{$name} ) {
if ( $old->{'address'} eq $alias->{'address'} &&
$old->{'dev'} eq $alias->{'dev'} &&
$old->{'name'} eq $alias->{'name'} ) {
if ( VERBOSE ) {
print STDERR "Interface $dev:$name"
. " is already up\n";
}
return( 1 );
}
if ( my $retval = aliasdown( $old, $runningconf ) ) {
return( $retval );
}
}
if ( VERBOSE ) {
print "Adding $alias->{'address'} to $alias->{'dev'}"
. " (label $alias->{'dev'}"
. ":$alias->{'name'})\n";
}
$result = runcmd( "ip address add $alias->{'address'}"
. " dev $alias->{'dev'}"
. " label $alias->{'dev'}:$alias->{'name'}" );
if ( VERBOSE ) {
if ( $result->{'stdout'} ) {
print $result->{'stdout'};
}
if ( $result->{'stderr'} ) {
print STDERR $result->{'stderr'};
}
}
return( $result->{'stat'} );
}
sub cidr2netmask {
my $cidr = shift;
my $bit = ( 2 ** ( 32 - $cidr ) ) - 1;
my $full_mask = unpack( 'N', pack( 'C4', 255,255,255,255 ) );
my $netmask = join( '.', unpack( 'C4', pack( 'N',
( $full_mask ^ $bit ) ) ) );
return( $netmask );
}
sub error {
my $status = shift;
my $errstr = shift;
my $level = 1;
my @stack = ();
chomp( $errstr );
print "\n";
print STDERR ( caller() )[1] .":\n $errstr at line "
. ( caller() )[2] . "\n";
if ( VERBOSE ) {
if ( caller( $level ) ) {
print "\n=== Stack Trace ===\n";
}
while ( my @trace = caller( $level++ ) ) {
print STDERR " $trace[1]:\n"
. " $trace[3]() called at line $trace[2]\n";
}
}
print "\n";
if ( $status ) {
exit( $status );
}
}
sub getroutes {
my $routes = {};
my $result = runcmd( 'ip route show' );
if ( $result->{'stat'} || ! $result->{'stdout'} ) {
return;
}
open( my $fh, '<', \$result->{'stdout'} );
while ( <$fh> ) {
if ( $_ =~ /^(\S+)\s+via\s+(\S+)\s+dev\s+(\S+)/ ) {
$routes->{$1}{'via'} = $2;
$routes->{$1}{'dev'} = $3;
}
}
close( $fh );
return( $routes );
}
sub ifdown {
my $iface = shift;
my $result = {};
my $stat = 0;
if ( VERBOSE ) {
print "Flushing interface $iface->{'name'}\n";
}
$result = runcmd( "ip addr flush dev $iface->{'name'}" );
if ( $result->{'stat'} ) {
$stat = $result->{'stat'};
}
if ( VERBOSE ) {
if ( $result->{'stdout'} ) {
print $result->{'stdout'};
}
if ( $result->{'stderr'} ) {
print STDERR $result->{'stderr'};
}
print "Bringing down interface $iface->{'name'}\n";
}
$result = runcmd( "ip link set $iface->{'name'} down" );
if ( $result->{'stat'} ) {
$stat = $result->{'stat'};
}
if ( VERBOSE ) {
if ( $result->{'stdout'} ) {
print $result->{'stdout'};
}
if ( $result->{'stderr'} ) {
print STDERR $result->{'stderr'};
}
}
return( $stat );
}
sub ifup {
my $iface = shift;
my $runningconf = shift;
my $routes = getroutes();
my $result;
my $stat = 0;
if ( my $old = $runningconf->{$iface->{'name'}} ) {
if ( ( $old->{'address'} && $iface->{'address'} &&
$old->{'address'} eq $iface->{'address'} ) ||
( $old->{'state'} eq 'UP' && $iface->{'inet'} eq 'dhcp' ) ) {
if ( VERBOSE ) {
print STDERR "Interface $iface->{'name'}"
. " is already up\n";
}
return;
}
if ( VERBOSE ) {
print "Flushing interface $iface->{'name'}\n";
}
$result = runcmd( "ip addr flush dev $iface->{'name'}" );
if ( VERBOSE ) {
if ( $result->{'stdout'} ) {
print $result->{'stdout'};
}
if ( $result->{'stderr'} ) {
print STDERR $result->{'stderr'};
}
}
if ( $result->{'stat'} ) {
return( $result->{'stat'} );
}
}
if ( $iface->{'macaddr'} ) {
if ( VERBOSE ) {
print "Setting MAC address on interface"
. " $iface->{'name'} to $iface->{'macaddr'}\n";
}
$result = runcmd( "ip link set dev $iface->{'name'}"
. " address $iface->{'macaddr'}" );
if ( VERBOSE ) {
if ( $result->{'stdout'} ) {
print $result->{'stdout'};
}
if ( $result->{'stderr'} ) {
print STDERR $result->{'stderr'};
}
}
if ( $result->{'stat'} ) {
return( $result->{'stat'} );
}
}
if ( VERBOSE ) {
print "Bringing up interface $iface->{'name'}\n";
}
if ( $iface->{'inet'} && $iface->{'inet'} eq 'static' ) {
if ( VERBOSE ) {
print "Setting address to $iface->{'address'}"
. " on interface $iface->{'name'}\n";
}
$result = runcmd( "ip address add $iface->{'address'}"
. " dev $iface->{'name'}" );
if ( VERBOSE ) {
if ( $result->{'stdout'} ) {
print $result->{'stdout'};
}
if ( $result->{'stderr'} ) {
print STDERR $result->{'stderr'};
}
}
if ( $result->{'stat'} ) {
return( $result->{'stat'} );
}
}
elsif ( $iface->{'inet'} && $iface->{'inet'} eq 'loopback' &&
! $runningconf->{$iface->{'name'}}{'name'} ) {
if ( VERBOSE ) {
print "Setting address to $iface->{'address'}"
. " on interface $iface->{'name'}\n";
}
$result = runcmd( "ip -d address add $iface->{'address'}"
. " dev $iface->{'name'}" );
if ( VERBOSE ) {
if ( $result->{'stdout'} ) {
print $result->{'stdout'};
}
if ( $result->{'stderr'} ) {
print STDERR $result->{'stderr'};
}
}
if ( $result->{'stat'} ) {
return( $result->{'stat'} );
}
}
elsif ( $iface->{'inet'} && $iface->{'inet'} eq 'dhcp' ) {
if ( -f '/var/run/dhclient.pid' ) {
system( "dhclient -r $iface->{'name'}" );
}
if ( VERBOSE ) {
print "Starting dhclient for $iface->{'name'}\n";
}
$result = runcmd( "dhclient $iface->{'name'}" );
if ( VERBOSE ) {
if ( $result->{'stdout'} ) {
print $result->{'stdout'};
}
if ( $result->{'stderr'} ) {
print STDERR $result->{'stderr'};
}
}
if ( $result->{'stat'} ) {
return( $result->{'stat'} );
}
}
$result = runcmd( "ip link set $iface->{'name'} up" );
if ( VERBOSE ) {
if ( $result->{'stdout'} ) {
print $result->{'stdout'};
}
if ( $result->{'stderr'} ) {
print STDERR $result->{'stderr'};
}
}
if ( $result->{'stat'} ) {
return( $result->{'stat'} );
}
if ( ! $routes->{'default'} && $iface->{'gateway'} ) {
if ( VERBOSE ) {
print "Adding default gateway $iface->{'gateway'}\n";
}
$result = runcmd( "ip route add default"
. " via $iface->{'gateway'}" );
if ( VERBOSE ) {
if ( $result->{'stdout'} ) {
print $result->{'stdout'};
}
if ( $result->{'stderr'} ) {
print STDERR $result->{'stderr'};
}
}
if ( $result->{'stat'} ) {
return( $result->{'stat'} );
}
}
elsif ( $routes->{'default'}{'via'} && $iface->{'gateway'} &&
$routes->{'default'}{'via'} ne $iface->{'gateway'} &&
$routes->{'default'}{'dev'} eq $iface->{'name'} ) {
if ( VERBOSE ) {
print "Changing default gateway to"
. " $iface->{'gateway'}\n";
}
$result = runcmd( "ip route delete default via"
. " $routes->{'default'}{'via'} dev $iface->{'name'}" );
if ( VERBOSE ) {
if ( $result->{'stdout'} ) {
print $result->{'stdout'};
}
if ( $result->{'stderr'} ) {
print STDERR $result->{'stderr'};
}
}
if ( $result->{'stat'} ) {
return( $result->{'stat'} );
}
$result = runcmd( "ip route add default"
. " via $iface->{'gateway'}" );
if ( VERBOSE ) {
if ( $result->{'stdout'} ) {
print $result->{'stdout'};
}
if ( $result->{'stderr'} ) {
print STDERR $result->{'stderr'};
}
}
if ( $result->{'stat'} ) {
return( $result->{'stat'} );
}
}
if ( $iface->{'routes'} ) {
foreach my $target ( keys( %{$iface->{'routes'}} ) ) {
if ( VERBOSE ) {
print "Adding route $target via"
. " $iface->{'routes'}{$target}"
. " dev $iface->{'name'}\n";
}
system( "ip route add $target via"
. " $iface->{'routes'}{$target}"
. " dev $iface->{'name'}" );
}
}
}
sub listfiles {
my $dir = shift;
my $files = [];
my $sorted = [];
if ( ! -d $dir ) {
return;
}
opendir( DIR, $dir ) || error( int( $! ), "opendir(): $dir: $!" );
while ( readdir( DIR ) ) {
if ( ! -f "$dir/$_" || $_ =~ /^\./ ) {
next;
}
push ( @$files, $_ );
}
@$sorted = sort( @$files );
return( $sorted );
}
sub netmask2cidr {
my $netmask = shift;
my $bits = {
0 => 0,
128 => 1,
192 => 2,
224 => 3,
240 => 4,
248 => 5,
252 => 6,
254 => 7,
255 => 8
};
my $lastoct;
my $cidr = 0;
foreach ( split( /\./, $netmask ) ) {
if ( ( $lastoct && $lastoct != 255 && $_ != 0 ) ||
! defined( $bits->{$_} ) ) {
error( int( $! ), "netmask2cidr(): $netmask:"
. " Invalid netmask" );
}
$cidr += $bits->{$_};
$lastoct = $_;
}
return( $cidr );
}
sub readconf {
my $file = shift;
my $conf = shift || {};
my $iface;
open( my $config, "<$file" ) || error( int( $! ), "open(): $file: $!" );
while ( <$config> ) {
if ( $_ =~ /^\s*#/ ) {
next;
}
if ( $_ =~ /source-directory\s+(\S+)/ ) {
my $path = $1;
my $files;
if ( substr( $path, 0, 1 ) ne '/' ) {
$path = CONFDIR . "/$path";
}
$files = listfiles( $path );
foreach my $file ( @$files ) {
readconf( "$path/$file", $conf );
}
}
elsif ( $_ =~ /auto\s+(\S+)/ && $1 =~ /^(\S+):(\S+)$/ ) {
$conf->{$1}{'aliases'}{$2}{'auto'} = 1;
}
elsif ( $_ =~ /auto\s+(\S+)/ ) {
$conf->{$1}{'auto'} = 1;
}
elsif ( $_ =~ /iface\s+(\S+):(\S+)/ ) {
$iface = "$1:$2";
$conf->{$1}{'aliases'}{$2}{'dev'} = $1;
$conf->{$1}{'aliases'}{$2}{'name'} = $2;
$conf->{$1}{'aliases'}{$2}{'cnt'} =
keys( %{$conf->{$1}{'aliases'}} );
}
elsif ( $_ =~ /iface\s+(\S+)\s+(\S+)\s+(\S+)/ ) {
$iface = $1;
if ( $conf->{$iface}{'inet'} ) {
error( -1, "Multiple instances of $iface"
. " in $file" );
}
$conf->{$iface}{$2} = $3;
$conf->{$iface}{'name'} = $iface;
if ( $3 eq 'loopback' ) {
$conf->{$iface}{'address'} = '127.0.0.1/8';
}
$conf->{$iface}{'cnt'} = scalar( keys( %$conf ) );
}
elsif ( $_ =~ /route\s+(\S+)\s+via\s+(\S+)/ ) {
$conf->{$iface}{'routes'}{$1} = $2;
}
elsif ( $iface && $_ =~ /^\s*(\S+)\s+(\S+)/ ) {
my ( $attr, $value ) = ( $1, $2 );
if ( $iface =~ /^(\S+):(\S+)/ ) {
$conf->{$1}{'aliases'}{$2}{$attr} = $value;
}
else {
$conf->{$iface}{$attr} = $value;
}
}
elsif ( $iface && $_ =~ /^\s*(\S+)\s+(\S+)/ ) {
$conf->{$iface}{$1} = $2;
}
}
close( $config );
foreach my $devname ( keys( %$conf ) ) {
my $dev = $conf->{$devname};
if ( $dev->{'address'} && $dev->{'netmask'} ) {
$dev->{'address'} .= '/'
. netmask2cidr( $dev->{'netmask'} );
undef( $dev->{'netmask'} );
}
if ( ! keys( %{$dev->{'aliases'}} ) ) {
next;
}
foreach my $aliasname ( keys( %{$dev->{'aliases'}} ) ) {
my $alias = $dev->{'aliases'}{$aliasname};
if ( $alias->{'address'} && $alias->{'netmask'} ) {
$alias->{'address'} .= '/'
. netmask2cidr( $alias->{'netmask'} );
undef( $alias->{'netmask'} );
}
}
}
return( $conf );
}
sub runcmd {
if ( NOACT ) {
return( { stat => 0 } );;
}
my $cmd = shift;
my $result = {
stdout => '',
stderr => '',
stat => ''
};
my $sel = IO::Select->new();
my $pid = eval {
return( open3( \*CHLDIN, \*CHLDOUT, \*CHLDERR, $cmd ) );
} || error( int( $! ), "open3(): $cmd: $!" );
close( CHLDIN );
$sel->add( *CHLDOUT, *CHLDERR );
while ( my @fhs = $sel->can_read ) {
foreach my $fh ( @fhs ) {
if ( eof( $fh ) ) {
$sel->remove( $fh );
next;
}
if ( fileno( $fh ) == fileno( *CHLDOUT ) ) {
$result->{'stdout'} .= <$fh>;
}
elsif ( fileno( $fh ) == fileno( *CHLDERR ) ) {
$result->{'stderr'} .= <$fh>;
}
}
}
close( CHLDOUT );
close( CHLDERR );
waitpid( $pid, 0 );
$result->{'stat'} = $? >> 8;
return( $result );
}
sub runningconf {
my $cmd = 'ip -d address show';
my $sel = IO::Select->new();
my $pid = eval {
return( open3( \*CHLDIN, \*CHLDOUT, \*CHLDERR, $cmd ) );
} || error( int( $! ), "open3(): $cmd: $!" );
my $stat;
my $stdout = '';
my $stderr = '';
my $runningconf = {};
my $macaddr;
my $dev;
close( CHLDIN );
$sel->add( *CHLDOUT, *CHLDERR );
while ( my @fhs = $sel->can_read ) {
foreach my $fh ( @fhs ) {
if ( eof( $fh ) ) {
$sel->remove( $fh );
next;
}
if ( fileno( $fh ) == fileno( *CHLDOUT ) ) {
$stdout .= <$fh>;
}
elsif ( fileno( $fh ) == fileno( *CHLDERR ) ) {
$stderr .= <$fh>;
}
}
}
close( CHLDOUT );
close( CHLDERR );
waitpid( $pid, 0 );
$stat = $? >> 8;
if ( $stat ) {
error( int( $! ), "open3: $cmd: $stderr" );
}
open( my $fh, '<', \$stdout ) || error( int( $! ), "open(): $!" );
while ( <$fh> ) {
if ( $_ =~ /^\d+:\s*(\S+):/ ) {
$dev = $1;
}
if ( $_ =~ /\s+mtu\s+(\d+)/ ) {
$runningconf->{$dev}{'mtu'} = $1;
}
if ( $_ =~ /\s+qdisc\s+(\S+)/ ) {
$runningconf->{$dev}{'qdisc'} = $1;
}
if ( $_ =~ /\s+state\s+(\S+)/ ) {
$runningconf->{$dev}{'state'} = $1;
}
if ( $_ =~ /\s+group\s+(\S+)/ ) {
$runningconf->{$dev}{'group'} = $1;
}
if ( $_ =~ /\s+qlen\s+(\S+)/ ) {
$runningconf->{$dev}{'qlen'} = $1;
}
if ( $_ =~ /^\s+link\/(\S+)\s+(\S+)/ ) {
$runningconf->{$dev}{'link'} = $1;
$runningconf->{$dev}{'macaddr'} = $2;
}
if ( $_ =~ /\s+promiscuity\s+(\S+)/ ) {
$runningconf->{$dev}{'promiscuity'} = $1;
}
if ( $_ =~ /^\s+inet\s+(\S+).*\s+(\S+):(\S+)/ ) {
$runningconf->{$2}{'aliases'}{$3}{'address'} = $1;
$runningconf->{$2}{'aliases'}{$3}{'dev'} = $dev;
$runningconf->{$2}{'aliases'}{$3}{'name'} = $3;
}
elsif ( $_ =~ /^\s+inet\s+(\S+).*(\S+)$/ ) {
if ( $runningconf->{$dev}{'address'} ) {
next;
}
$runningconf->{$dev}{'address'} = $1;
}
}
close( $fh );
return( $runningconf );
}
my $conf = readconf( CONFIGFILE );
my $runningconf = runningconf();
my $self = ( split( '/', $0 ) )[-1];
my $ifaces = [];
my $all = eval {
for ( my $i = 0; $i <= $#ARGV; $i++ ) {
if ( $ARGV[$i] eq '-a' || $ARGV[$i] eq '--all' ) {
splice( @ARGV, $i, 1 );
return( 1 );
}
}
};
my $stat = 0;
#print Dumper( $conf ); exit;
if ( grep( $_ eq '-h' || $_ eq '--help', @ARGV ) ) {
print "Usage: $self [OPTIONS] [INTERFACES]\n";
if ( $self eq 'ifup' ) {
print "Bring a network interface up\n\n";
}
elsif ( $self eq 'ifdown' ) {
print "Bring a network interface down\n\n";
}
elsif ( $self eq 'ifreload' ) {
print "Reload interface configuration\n\n";
}
elsif ( $self eq 'ifquery' ) {
print "View current status of interfaces\n\n";
}
print "Options:\n"
. "\t-a, --all\t\tperform actions on all 'auto' interfaces\n"
. "\t-h, --help\t\tprint usage information\n";
if ( $self ne 'ifquery' ) {
print "\t-n, --no-act\t\tdisplay actions without taking them\n"
. "\t-v, --verbose\t\tdisplay actions as they occur\n";
}
print "\t-V, --version\t\tdisplay version information\n";
exit( 0 );
}
elsif ( grep( $_ eq '-V' || $_ eq '--version', @ARGV ) ) {
print "iftools version " . VERSION . "\n";
exit( 0 );
}
if ( ! $all ) {
foreach ( @ARGV ) {
( my $dev = $_ ) =~ s/:.*//;
if ( $runningconf->{$dev} ) {
push( @$ifaces, $_ );
}
elsif ( VERBOSE ) {
print STDERR "$_: No such device\n";
}
}
}
else {
foreach ( sort { $conf->{$a}{'cnt'} <=> $conf->{$b}{'cnt'} }
( keys( %$conf ) ) ) {
( my $dev = $_ ) =~ s/:.*//;
if ( $self eq 'ifup' && ! $conf->{$_}{'auto'} ) {
next;
}
if ( $runningconf->{$dev} ) {
push( @$ifaces, $_ );
}
elsif ( VERBOSE ) {
print STDERR "$_: No such device\n";
next;
}
foreach my $alias ( sort {
$conf->{$dev}{'aliases'}{$a}{'cnt'} <=>
$conf->{$dev}{'aliases'}{$b}{'cnt'} }
keys( %{$conf->{$dev}{'aliases'}} ) ) {
push( @$ifaces, "$dev:$alias" );
}
}
}
foreach my $iface ( @$ifaces ) {
if ( $self eq 'ifup' ) {
if ( $iface =~ /^(\S+):(\S+)/ ) {
$stat = aliasup( $conf->{$1}{'aliases'}{$2},
$runningconf ) || $stat;
}
else {
$stat = ifup( $conf->{$iface}, $runningconf ) || $stat;
}
}
elsif ( $self eq 'ifdown' ) {
if ( $iface =~ /^(\S+):(\S+)/ ) {
$stat = aliasdown( $conf->{$1}{'aliases'}{$2},
$runningconf ) || $stat;
}
else {
$stat = ifdown( $conf->{$iface}, $runningconf ) ||
$stat;
}
}
elsif ( $self eq 'ifreload' ) {
if ( $iface =~ /^(\S+):(\S+)/ ) {
$stat = aliasdown( $conf->{$1}{'aliases'}{$2},
$runningconf ) || $stat;
$runningconf = runningconf();
$stat = aliasup( $conf->{$1}{'aliases'}{$2},
$runningconf ) || $stat;
}
else {
$stat = ifdown( $conf->{$iface}, $runningconf ) ||
$stat;
$runningconf = runningconf();
$stat = ifup( $conf->{$iface}, $runningconf ) ||
$stat;
}
}
elsif ( $self eq 'ifquery' ) {
if ( $iface =~ /^\S+:\S+/ ) {
next;
}
elsif ( ! $runningconf->{$iface} ) {
$runningconf->{$iface} = {
state => 'No such device',
address => '',
macaddr => ''
};
}
print "[$iface]\n"
. " State: $runningconf->{$iface}{'state'}\n"
. " Address: $runningconf->{$iface}{'address'}\n"
. " MAC: $runningconf->{$iface}{'macaddr'}\n";
foreach my $name ( sort( keys(
%{$runningconf->{$iface}{'aliases'}} ) ) ) {
my $alias = $runningconf->{$iface}{'aliases'}{$name};
print "[$iface:$name]\n"
. " Address: $alias->{'address'}\n";
}
}
$runningconf = runningconf();
}
close( SELF );
exit( $stat );

98
SRC/ifup.8 Normal file
View File

@@ -0,0 +1,98 @@
.TH ifup 8 "May 2017" "iftools" "Linux System Administrator's Manual"
.SH NAME
ifup \- bring a network interface up
.br
ifdown \- take a network interface down
.br
ifreload \- reload interface configuration
.br
ifquery \- view current state of interfaces
.SH SYNOPSIS
.B ifup
\f |
.B ifdown
\f |
.B ifreload
\f |
.B ifquery
\f <OPTIONS> <INTERFACES>
.SH DESCRIPTION
The
.BR ifup " and " ifdown
commands may be used to configure (or, respectively, deconfigure) network
interfaces based on interface definitions in the file
.IR /etc/network.conf ". The"
.BR ifreload " command will perform an ifdown and ifup in one command."
.BR ifquery " may be used to display the running configuration."
.SH OPTIONS
A summary of options is included below.
.TP
.BR \-a ", " \-\-all
If given to \fBifup\fP, affect all interfaces marked \fBauto\fP.
Interfaces are brought up in the order in which they are defined
in
.IR /etc/network.conf .
If given to \fBifdown\fP, affect all defined interfaces.
Interfaces are brought down in the order in which they are
listed in the configuration files.
.TP
.BR \-h ", " \-\-help
Show summary of options.
.TP
.BR \-n ", " \-\-no\-act
Don't configure any interfaces or run any "up" or "down" commands.
.TP
.BR \-V ", " \-\-version
Show copyright and version information.
.TP
.BR \-v ", " \-\-verbose
Show commands as they are executed.
.SH EXAMPLES
.TP
.B ifup -a
Bring up all the interfaces defined with
.I auto
in
.nh
.I /etc/network.conf
.TP
.B ifup eth0
Bring up interface
.B eth0
.TP
.B ifdown -a
Bring down all interfaces that are currently up.
.TP
.B ifquery eth0
Print the running configuration of eth0
.SH NOTES
.BR ifup ,
.BR ifdown ,
.BR ifreload ,
and
.BR ifquery
are actually the same program called by different names.
.P
The program does not configure network interfaces directly;
it runs low level utilities such as
.BR ip
to do its dirty work.
.P
When invoked a check will be performed to verify that there
are no other instances running. If another instance is
detected the program will exit with an error.
.SH FILES
.TP
.I /etc/network.conf
definitions of network interfaces
See
.BR network.conf (5)
for more information.
.TP
.I /run/network/ifstate
current state of network interfaces
.SH AUTHOR
iftools was written by Jay Larson <jlarson@snaplinux.org>. The functionality is loosely based on the ifupdown suite written by Anthony Towns <aj@azure.humbug.org.au>.
.SH SEE ALSO
.BR network.conf (5),
.BR ip (8)

89
SRC/network.conf.5 Normal file
View File

@@ -0,0 +1,89 @@
.TH network.conf 5 "May 2017" "iftools" "File formats"
.SH NAME
/etc/network.conf \- network interface configuration for iftools
.SH DESCRIPTION
/etc/network.conf contains network interface configuration
information for the
.BR ifup (8)
and
.BR ifdown (8)
commands.
This is where you configure how your system is connected to the network.
.P
Lines starting with `#' are ignored. Note that end-of-line comments are
NOT supported, comments must be on a line of their own.
.P
The file consists of any number of "iface", "auto", and
.nh
"source\-directory" stanzas. Here is an example:
.P
.RS
.EX
auto eth0
iface eth0 inet static
address 192.168.1.10
netmask 255.255.255.0
gateway 192.168.1.1
iface eth1 inet dhcp
iface eth1:1
address 192.168.1.2
netmask 255.255.255.0
source-directory network.d
.EE
.RE
.P
Lines beginning with the word "auto" are used to identify the physical
interfaces to be brought up when
.B ifup
is run with the
.B \-a
option. (This option is used by the system boot scripts.)
There can be multiple "auto" stanzas.
.B ifup
brings the named interfaces up in the order listed.
.P
Lines beginning with "source-directory" are used to source multiple
files at once. All non-dotted files within the directory are sourced
in lexical order.
.P
When sourcing directories, if a path doesn't have a leading slash
it's considered relative to the directory containing the network.conf
file (/etc). In the example above, files in /etc/network.d are sourced.
.P
By default, on a freshly installed system, the network.conf file includes
a line to source files in the
.IR /etc/network.d
directory.
.P
Stanzas defining logical interfaces start with a line consisting of the
word "iface" followed by the name of the logical interface. The name
should be the name of the physical interface, a colon, and the logical
name. This is shown in the example above as eth1:1.
.P
Additional options can be given on subsequent lines in the stanza.
Options are usually indented for clarity (as in the example above)
but are not required to be.
.P
.SH OPTIONS
The following additional options are available:
.TP
.BR macaddr " XX:XX:XX:XX:XX:XX"
Set the MAC address to be used by a physical interface. This option
cannot be applied to logical interfaces.
.TP
.BR route " [NETWORK|IP] " via " [GATEWAY]"
Specify a gateway for a particular network or IP address. The network
or IP address can be specified in CIDR notation. This option is also
only available for physical devices.
.SH AUTHOR
iftools was written by Jay Larson <jlarson@snaplinux.org>. The functionality is
loosely based on the ifupdown suite written by Anthony Towns <aj@azure.humbug.org.au>.
.SH "SEE ALSO"
.BR ifup (8),
.BR ip (8),
.BR ifconfig (8),
.BR run\-parts (8),
.BR resolvconf (8).

3
SRC/patches/README Normal file
View File

@@ -0,0 +1,3 @@
Place any patch files here and preface each with a
number indicating the order of execution. Patch
files are expected to use a .patch extension.