summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Estabrook <jestabro@vyos.io>2021-09-30 12:56:57 -0500
committerGitHub <noreply@github.com>2021-09-30 12:56:57 -0500
commit4e0adbe9fcfccb6b1afd70e745aefa5244deaa62 (patch)
tree4f6deae8ab5638011fb331b5dcb95e4cb835d95c
parenteb8c1520766b9b44c72c9359eeda3faff00db7b2 (diff)
parent7500ce0fc8ed65da2dd763a193122c5769b95520 (diff)
downloadvyatta-cfg-system-4e0adbe9fcfccb6b1afd70e745aefa5244deaa62.tar.gz
vyatta-cfg-system-4e0adbe9fcfccb6b1afd70e745aefa5244deaa62.zip
Merge pull request #171 from jestabro/interface-names
interface-names: T3869: use vyos-interface-rescan instead of legacy
-rw-r--r--Makefile.am8
-rw-r--r--scripts/XorpConfigParser.pm618
-rwxr-xr-xscripts/system/vyatta_interface_rescan168
-rwxr-xr-xscripts/vyatta_net_name278
4 files changed, 0 insertions, 1072 deletions
diff --git a/Makefile.am b/Makefile.am
index 1794a4e7..940bccce 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,7 +2,6 @@ bin_sudo_usersdir = $(bindir)/sudo-users
curverdir = $(sysconfdir)/config-migrate/current
checkparamsonrebootdir = $(bindir)/sudo-users/check-params-on-reboot.d
initddir = /etc/init.d
-share_perl5dir = $(datadir)/perl5
bin_SCRIPTS =
sbin_SCRIPTS =
@@ -21,7 +20,6 @@ sbin_SCRIPTS += scripts/vyatta-dhcp-helper.pl
sbin_SCRIPTS += scripts/check_file_in_config_dir
sbin_SCRIPTS += scripts/vyatta-grub-setup
sbin_SCRIPTS += scripts/standalone_root_pw_reset
-sbin_SCRIPTS += scripts/system/vyatta_interface_rescan
sbin_SCRIPTS += scripts/system/vyatta_update_sysctl.pl
sbin_SCRIPTS += scripts/snmp/if-mib-alias
sbin_SCRIPTS += scripts/vyatta-interfaces.pl
@@ -38,16 +36,10 @@ sbin_SCRIPTS += scripts/install/install-image
sbin_SCRIPTS += scripts/vyatta-dhcpv6-client.pl
sbin_SCRIPTS += scripts/vyos-persistpath
-share_perl5_DATA =
-share_perl5_DATA += scripts/XorpConfigParser.pm
-
sysconf_DATA += sysconf/LICENSE
sysconf_DATA += sysconf/filecaps
sysconf_DATA += sysconf/netdevice
-libudevdir = /lib/udev
-libudev_SCRIPTS = scripts/vyatta_net_name
-
rsyslogdir = /etc/rsyslog.d
curver_DATA = cfg-version/vrrp@3
diff --git a/scripts/XorpConfigParser.pm b/scripts/XorpConfigParser.pm
deleted file mode 100644
index 3a4035f8..00000000
--- a/scripts/XorpConfigParser.pm
+++ /dev/null
@@ -1,618 +0,0 @@
-# Perl module for parsing config files.
-
-use lib "/opt/vyatta/share/perl5/";
-
-package XorpConfigParser;
-
-use strict;
-my %data;
-
-my %fields = ( _data => \%data );
-
-sub new {
- my $that = shift;
- my $class = ref($that) || $that;
- my $self = { %fields, };
-
- bless $self, $class;
- return $self;
-}
-
-#
-# This method is used to copy nodes whose names begin with a particular string
-# from one array to another.
-#
-# Parameters:
-#
-# $from Reference to the source array
-# $to Reference to the destination array
-# $name The string with which the beginning of the node names will be matched
-#
-sub copy_node {
- my ( $self, $from, $to, $name ) = @_;
- if ( !defined($from) || !defined($to) || !defined($name) ) {
- return;
- }
-
- foreach my $node (@$from) {
- my $stringNodeNameHere = $node->{'name'};
- if ( $stringNodeNameHere =~ /^$name.*/ ) {
- foreach my $nodeCheck (@$to) {
- my $stringCheck = $nodeCheck->{'name'};
- if ( $name eq $stringCheck ) {
- $nodeCheck->{'value'} = $node->{'value'};
- $nodeCheck->{'children'} = $node->{'children'};
- $nodeCheck->{'comment'} = $node->{'comment'};
- $nodeCheck->{'disable'} = $node->{'disable'};
- return;
- }
- }
- push( @$to, $node );
- }
- }
-}
-
-#
-# This method is used to create duplicate copies of multinodes with the name
-# specified, and to return the new copies in a new array.
-#
-# $nodes A reference to an array of multinodes
-# $name The name of the multinodes to copy into the new array
-#
-sub copy_multis {
- my ( $self, $nodes, $name ) = @_;
-
- return if ( !defined($nodes) || !defined($name) );
-
- my @multis;
-
- foreach my $node (@$nodes) {
- my $stringNodeNameHere = $node->{'name'};
- if ( $stringNodeNameHere =~ /$name\s(\S+)/ ) {
- my $stringNameHere = $1;
- my %multi = (
- 'name' => $stringNameHere,
- 'comment' => $node->{'comment'},
- 'value' => $node->{'value'},
- 'disable' => $node->{'disable'},
- 'children' => $node->{'children'}
- );
- push( @multis, \%multi );
- }
- }
-
- return @multis;
-}
-
-#
-# This method is used to comment out a particular child.
-#
-# $children A reference to an array of children
-# $name The name of the child to comment out
-# $comment The comment string that will be included inside the comment
-#
-sub comment_out_child {
- my ( $self, $children, $name, $comment ) = @_;
- if ( !defined($children) || !defined($name) ) {
- return;
- }
-
- for ( my $i = 0 ; $i < @$children ; $i++ ) {
- my $stringNodeNameHere = @$children[$i]->{'name'};
- if ( $name eq $stringNodeNameHere ) {
- $self->comment_out_node( @$children[$i] );
- if ( defined($comment) ) {
- @$children[$i]->{'comment_out'} = $comment;
- }
- }
- }
-}
-
-#
-# This method is used to comment out a particular node.
-#
-# $node A reference to the node to comment out
-#
-sub comment_out_node {
- my ( $self, $node ) = @_;
- if ( !defined($node) ) {
- return;
- }
-
- $node->{'comment_out'} = "1";
-}
-
-#
-# This method is used to create a node with the path specified. The method
-# will create parent nodes as necessary.
-#
-# $path A reference to the array containing the path segments
-#
-sub create_node {
- my ( $self, $path ) = @_;
-
- my $hash = \%data;
- SEGMENT:
- foreach my $segment (@$path) {
- my $children = $hash->{'children'};
-
- unless ($children) {
- my @new_children;
- $hash->{'children'} = \@new_children;
- $children = \@new_children;
- }
-
- foreach my $child (@$children) {
- my $name = $child->{'name'};
- next unless $name;
-
- if ( $name eq $segment ) {
- $hash = $child; # record insertion point
- next SEGMENT;
- }
- }
-
- my %new_hash = ( 'name' => $segment );
-
- if ($hash != \%data) {
- # insertion in subtree
- push @$children, \%new_hash;
- } else {
- # special case for insertion at top put new before version comment
- my @comments;
- while (my $child = pop @$children) {
- if ($child->{'comment'}) {
- unshift @comments, $child;
- } else {
- push @$children, $child;
- last;
- }
- }
-
- push @$children, \%new_hash;
- push @$children, @comments;
- }
- $hash = \%new_hash;
- }
- return $hash;
-}
-
-#
-# This method is used to delete a child node with the name specified from an array of child nodes.
-#
-# $children A reference to the array of child nodes
-# $name The name of the child node to delete
-#
-sub delete_child {
- my ( $self, $children, $name ) = @_;
- return if ( !defined($children) || !defined($name) );
-
- for ( my $i = 0 ; $i < @$children ; $i++ ) {
- my $stringNodeNameHere = @$children[$i]->{'name'};
- if ( $name eq $stringNodeNameHere ) {
- @$children[$i] = undef;
- }
- }
-}
-
-#
-# This method is used to return a reference to the child node
-# with the name specified.
-#
-# $children A reference to an array containing the child nodes.
-# $name The name of the child node reference to which will be returned.
-#
-# If the child node with the name specified is not found,
-# then 'undef' is returned.
-#
-sub find_child {
- my ( $self, $children, $name ) = @_;
- return if ( !defined($children) || !defined($name) );
-
- foreach my $child (@$children) {
- return $child if ( $name eq $child->{'name'} );
- }
- return;
-}
-
-# $ref: reference to the node to be used as the starting point.
-# the same as node_exists() except that the starting point is the specified
-# node (instead of root).
-sub node_exists_with_ref {
- my ( $self, $ref, $path ) = @_;
- my @parr = split / /, $path;
- if ( defined( $self->get_node_with_ref( $ref, \@parr ) ) ) {
- return 1;
- }
- return 0;
-}
-
-# $path: a space-delimited string representing the path to a node.
-# e.g., 'interfaces ethernet eth0'. note that the path
-# is relative from the root level.
-# returns 1 if the specified node exists. otherwise returns 0.
-sub node_exists {
- my ( $self, $path ) = @_;
- my @parr = split / /, $path;
-
- return $self->get_node( \@parr );
-}
-
-# $ref: reference to the node to be used as the starting point.
-# the same as get_node() except that the starting point is the specified
-# node (instead of root).
-sub get_node_with_ref {
- my ( $self, $ref, $path ) = @_;
- my $hash = $ref;
-
- SEGMENT:
- foreach my $segment (@$path) {
- my $children = $hash->{'children'};
- return unless $children;
-
- foreach my $child (@$children) {
- next unless ( $child->{'name'} eq $segment );
-
- $hash = $child;
- next SEGMENT;
- }
-
- # No children matched segment
- return;
- }
-
- return $hash;
-}
-
-#
-# This method is used to return a reference to the hash
-# of the node with the path specified.
-#
-# $path - reference to an array containing the path segments of the node.
-#
-# If the path is invalid, then undef is returned.
-sub get_node {
- my ( $self, $path ) = @_;
-
- return $self->get_node_with_ref( $self->{_data}, $path );
-}
-
-#
-# Move a subtree from one place to another in hierarchy
-# Assumes both $from and $to exist
-# Returns undef if no match
-sub move_child {
- my ( $self, $from, $to, $name ) = @_;
- my $source = $from->{'children'};
- return unless $source;
-
- for ( my $i = 0 ; $i < @$source ; $i++ ) {
- my $match = @$source[$i];
- next unless $match->{'name'} eq $name;
- splice @$source, $i, 1; # remove old list
-
- my $children = $to->{'children'};
- unless ($children) {
- my @new_children;
- $to->{'children'} = \@new_children;
- $children = \@new_children;
- }
-
- push @$children, $match;
- return $match;
- }
-
- return;
-}
-
-#
-# This method is used to insert a comment at a particular path.
-#
-# $path A reference to an array containing the path segments to the
-# node for which the comment is to be inserted. The comment
-# will appear above the node.
-#
-# If the node with the path specified does not exist, a node with empty name
-# will be created for the comment.
-#
-sub push_comment {
- my ( $self, $path, $comment ) = @_;
-
- my $hash = \%data;
- foreach my $segment (@$path) {
- my $children = $hash->{'children'};
- if ( !defined($children) ) {
- my @children;
- $hash->{'children'} = \@children;
- $children = \@children;
- }
-
- my $child_found = 0;
- foreach my $child (@$children) {
- if ( $child->{'name'} eq $segment ) {
- $child_found = 1;
- $hash = $child;
- last;
- }
- }
-
- if ( $child_found == 0 ) {
- my %new_hash = ( 'name' => $segment );
- push( @$children, \%new_hash );
- $hash = \%new_hash;
- }
- }
-
- my %new_comment = ( 'comment' => $comment );
- my $childrenPush = $hash->{'children'};
- if ( !defined($childrenPush) ) {
- my @new_children;
- $hash->{'children'} = \@new_children;
- $childrenPush = \@new_children;
- }
- push( @$childrenPush, \%new_comment );
-}
-
-#
-# This method is used to set the value of a particular node
-#
-# $path A reference to an array containing the path segments to the node
-# $value String of the value to set
-#
-sub set_value {
- my ( $self, $path, $value ) = @_;
-
- my $hash = $self->create_node($path);
- if ( defined($hash) ) {
- $hash->{'value'} = $value;
- }
-}
-
-#
-# This method is used to set the value of a particular node
-#
-# $path A reference to an array containing the path segments to the node
-# $value String of the value to set
-#
-sub set_disable {
- my ( $self, $path ) = @_;
- my $hash = $self->create_node($path);
- if ( defined($hash) ) {
- $hash->{'disable'} = 'true';
- }
-}
-
-#
-# This method is used to generate the output of the node tree in the XORP config
-# file format. The output is printed out to currently selected standard out.
-#
-# $depth Number of indents, used when this method calls itself
-# recursively, should be 0 when used.
-# $hash A reference to the parent node, should be the roor node when
-# used.
-#
-sub output {
- my ( $self, $depth, $hash ) = @_;
-
- $hash = $self->{_data} unless $hash;
-
- my $comment = $hash->{'comment'};
- print '/*' . $comment . "*/\n"
- if $comment;
-
- my $children = $hash->{'children'};
- foreach my $child (@$children) {
- next unless $child;
- my $name = $child->{'name'};
-
- my $comment_out = $child->{'comment_out'};
- if ($comment_out) {
- print "\n";
- print "/* --- $comment_out --- */\n"
- if ( $comment_out ne "1" );
- print
-"/* --- CONFIGURATION COMMENTED OUT DURING MIGRATION BELOW ---\n";
- }
-
- print " " x $depth;
- my $value = $child->{'value'};
- if ($value) {
- print "$name $value";
- print "\n";
- }
- else {
- my $print_brackets = 0;
- my $children = $child->{'children'};
- if ( defined($children) && @$children > 0 ) {
- $print_brackets = 1;
- }
- elsif ( defined($name) && !( $name =~ /\s/ ) ) {
- $print_brackets = 1;
- }
-
- if ($name) {
- print "$name";
- if ($print_brackets) {
- print " {";
- }
- print "\n";
- }
-
- $self->output( $depth + 1, $child );
- if ($print_brackets) {
- print " " x $depth;
- print "}\n";
- }
- }
-
- print
-" --- CONFIGURATION COMMENTED OUT DURING MIGRATION ABOVE --- */\n\n"
- if ($comment_out);
- }
-}
-
-#
-# This method is used to parse the XORP config file specified into the internal tree
-# structure that the methods above process and manipulate.
-#
-# $file String of the filename to parse
-#
-sub parse {
- my ( $self, $file ) = @_;
-
- %data = ();
-
- open my $in, '<', $file
- or die "Error! Unable to open file \"$file\". $!";
-
- my $contents = "";
- while (<$in>) {
- $contents .= $_;
- }
- close $in;
-
- my @array_contents = split( '', $contents );
-
- # print scalar(@array_contents) . "\n";
-
- my $length_contents = @array_contents;
- my $colon = 0;
- my $colon_quote = 0;
- my $in_quote = 0;
- my $name = '';
- my $value = undef;
- my $disable = undef;
- my @path;
- my %tree;
-
- for ( my $i = 0 ; $i < $length_contents ; ) {
- my $c = $array_contents[$i];
- my $cNext = $array_contents[ $i + 1 ];
-
- if ( $colon == 1 ) {
- my $value_end = 0;
- if ( $c eq '"' ) {
- $value .= $c;
- if ( $colon_quote == 1 ) {
- $value_end = 1;
- }
- else {
- $colon_quote = 1;
- }
- }
- elsif ( $c eq '\\' && $cNext eq '"' ) {
- $value .= '\\"';
- $i++;
- }
- elsif ( defined($value) ) {
- if ( ( length($value) > 0 ) || ( !( $c =~ /\s/ ) ) ) {
- $value .= $c;
- }
- }
-
- if ( $colon_quote == 0
- && ( $cNext eq '}' || $cNext eq ';' || $cNext =~ /\s/ ) )
- {
- $value_end = 1;
- }
- $i++;
-
- if ( $value_end == 1 ) {
- if ( length($value) > 0 ) {
-
- # print "Path is: \"@path\" Value is: $value\n";
- $self->set_value( \@path, $value );
- $value = undef;
- }
- pop(@path);
- $colon_quote = 0;
- $colon = 0;
- }
- next;
- }
-
- # ! $colon
- # check for quotes
- if ( $c eq '"' ) {
- if ($in_quote) {
- $in_quote = 0;
- }
- else {
- $in_quote = 1;
- }
- $name .= '"';
- $i++;
- next;
- }
- elsif ( $c eq '\\' && $cNext eq '"' ) {
- $name .= '\\"';
- $i += 2;
- next;
- }
-
- if ( !$in_quote && $c eq '!' && $cNext eq ' ') {
- $disable = 'true';
- $i += 2;
- }
- elsif ( !$in_quote && $c eq '/' && $cNext eq '*' ) {
- my $comment_text = '';
- my $comment_end = index( $contents, '*/', $i + 2 );
- if ( $comment_end == -1 ) {
- $comment_text = substr( $contents, $i + 2 );
- }
- else {
- $comment_text =
- substr( $contents, $i + 2, $comment_end - $i - 2 );
- $i = $comment_end + 2;
- }
-
- # print 'Comment is: "' . $comment_text . "\"\n";
- $self->push_comment( \@path, $comment_text );
- }
- elsif (( !$in_quote && $c eq '{' )
- || ( $c eq ':' && !( $name =~ /\s/ ) )
- || $c eq "\n" )
- {
- $name =~ s/^\s+|\s$//g;
-
- if ( length($name) > 0 ) {
- push( @path, $name );
-
- if (defined $disable && $disable eq 'true') {
- $self->set_disable(\@path);
- $disable = undef;
- }
-
- # print "Path is: \"@path\" Name is: \"$name\"\n";
- $self->set_value( \@path, $value );
- $name = '';
-
- if ( $c eq "\n" ) {
- pop(@path);
- }
- if ( $c eq ':' ) {
- $colon = 1;
- }
- }
-
- $i++;
- }
- elsif ( !$in_quote && $c eq '}' ) {
- pop(@path);
- $name = '';
- $disable = undef;
- $i++;
- }
- elsif ( !$in_quote && $c eq ';' ) {
- $i++;
- }
- else {
- if ( ( length($name) > 0 ) || ( !( $c =~ /\s/ ) ) ) {
- $name .= $c;
- }
- $i++;
- }
- }
-}
-
-1;
diff --git a/scripts/system/vyatta_interface_rescan b/scripts/system/vyatta_interface_rescan
deleted file mode 100755
index 2e8ad8ca..00000000
--- a/scripts/system/vyatta_interface_rescan
+++ /dev/null
@@ -1,168 +0,0 @@
-#! /usr/bin/perl
-
-# 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.
-#
-# This code was originally developed by Vyatta, Inc.
-# Portions created by Vyatta are Copyright (C) 2010 Vyatta, Inc.
-# All Rights Reserved.
-
-# Thus updates the configuration to add new interfaces.
-# It is run on boot after udev and before vyatta configuration.
-
-use strict;
-use lib "/opt/vyatta/share/perl5/";
-use Sys::Syslog qw(:standard :macros);
-use XorpConfigParser;
-use File::Copy;
-
-my $TMPFILE = "/tmp/config.boot.$$";
-
-# These vendors are known to violate the local MAC address assignment convention
-my %whitelist = (
- '02:07:01' => 'Interlan',
- '02:60:60' => '3Com',
- '02:60:8c' => '3Com',
- '02:a0:c9' => 'Intel',
- '02:aa:3c' => 'Olivetti',
- '02:cf:1f' => 'CMC',
- '02:e0:3b' => 'Prominet',
- '02:e6:d3' => 'BTI',
- '52:54:00' => 'Realtek',
- '52:54:4c' => 'Novell 2000',
- '52:54:ab' => 'Realtec',
- 'e2:0c:0f' => 'Kingston Technologies',
-);
-
-# Ignore devices with local assigned or invalid mac address,
-# these devices don't have a persistent address
-sub persistent_address {
- my $mac = shift;
-
- return if ($mac eq '00:00:00:00:00:00'); # zero address is reserved
-
- # get first octet
- return unless ($mac =~ /^([0-9a-f][0-9a-f]):/);
- my $oct0 = hex($1);
-
- return if ($oct0 & 0x1); # skip it is a multicast address
-
- return 1 unless ($oct0 & 0x2); # this is good, not locally assigned
-
- return 1 if ( -d '/proc/xen' ); # workaround Xen breakage
-
- # unless it is in whitelist, it is non persistent
- $mac =~ /^([0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f])/;
- return $whitelist{$1};
-}
-
-# Map from eth0 to ethernet
-# TODO make smarter if more types
-sub interface_type {
- my $ifname = shift;
-
- return "ethernet" if ($ifname =~ /^eth/);
- return "wireless" if ($ifname =~ /^wlan/);
-
- die "unknown interface name %s\n", $ifname;
-}
-
-sub get_hwid {
- my $name = shift;
-
- open (my $f, '<', $name)
- or die "Can't open $name : $!";
-
- my $hwaddr = <$f>;
- chomp $hwaddr;
- close $f;
-
- return $hwaddr;
-}
-
-# Determine phy for wlan device
-# (This is ugly)
-sub get_phy {
- my $wlan = shift;
- my $phypath = "/sys/class/net/$wlan/phy80211";
-
- # link should be: ../../ieee80211/phy0
- return unless (readlink($phypath) =~ m!../../ieee80211/(phy[0-9]+)$!);
-
- return $1;
-}
-
-# vyatta_net_name leaves files in /run/udev/vyatta
-# the filename is the interface and the contents are the hardware id
-sub interface_rescan {
- my ($VYATTAUDEV, $BOOTFILE) = @_;
-
- # parse existing config
- my $xcp = new XorpConfigParser();
- $xcp->parse($BOOTFILE);
-
- # get list of changed interfaces
- opendir( my $dir, $VYATTAUDEV )
- or die "Can't open $VYATTAUDEV : $!";
- my @interfaces = grep { ! /^\./ } readdir($dir);
- close $dir;
-
- foreach my $ifname (sort @interfaces) {
- my $hwaddr = get_hwid("$VYATTAUDEV/$ifname");
-
- # Ignore devices that disappear (or get renamed)
- unless (-d "/sys/class/net/$ifname") {
- syslog(LOG_INFO, "%s: does not exist", $ifname);
- next;
- }
-
- unless (persistent_address($hwaddr)) {
- syslog(LOG_NOTICE, "%s: skipping address %s is not persistent",
- $ifname, $hwaddr);
- next;
- }
-
- # Add new entry to config
- my $ifpath = interface_type($ifname) . " $ifname";
-
- syslog(LOG_INFO, "add config for %s hw-id %s", $ifname, $hwaddr);
- $xcp->create_node(['interfaces',$ifpath,"hw-id $hwaddr"]);
-
- # Add existing phy entry for wireless
- if ($ifname =~ /^wlan/) {
- my $phy = get_phy($ifname);
- $xcp->create_node(['interfaces',$ifpath,"physical-device $phy"]) if $phy;
- }
-
- }
-
- # Rewrite new config file
- open (my $tmp, '>', $TMPFILE)
- or die "Can't open $TMPFILE : $!";
-
- select $tmp;
- $xcp->output(0);
- select STDOUT;
- close $tmp;
-
- copy($TMPFILE, $BOOTFILE)
- or die "Can't copy $TMPFILE to $BOOTFILE : $!";
-
- unlink($TMPFILE);
-}
-
-# main
-die "vyatta_interface_rescan called with wrong args"
- unless ($#ARGV == 1);
-
-openlog("vyatta-interface-rescan", "", LOG_DAEMON);
-
-interface_rescan(@ARGV);
-exit 0;
-
diff --git a/scripts/vyatta_net_name b/scripts/vyatta_net_name
deleted file mode 100755
index d61ac6a3..00000000
--- a/scripts/vyatta_net_name
+++ /dev/null
@@ -1,278 +0,0 @@
-#! /usr/bin/perl
-
-# 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.
-#
-# This code was originally developed by Vyatta, Inc.
-# Portions created by Vyatta are Copyright (C) 2010 Vyatta, Inc.
-# All Rights Reserved.
-
-use strict;
-use lib "/opt/vyatta/share/perl5/";
-use XorpConfigParser;
-use Vyatta::Config;
-use Sys::Syslog qw(:standard :macros);
-use Fcntl qw(:flock);
-
-my $BOOTFILE = "/opt/vyatta/etc/config/config.boot";
-my $VYATTACFG = "/opt/vyatta/config/active/interfaces";
-
-my $UDEVDIR = "/run/udev/";
-my $VYATTAUDEV = $UDEVDIR . "vyatta";
-my $LOCKFILE = $UDEVDIR . ".vyatta-lock";
-my $UDEVLOG = $UDEVDIR . "log/";
-my $LOGFILE = $UDEVLOG . "vyatta-net-name.coldplug";
-
-# Check if interface name is free to use
-sub is_available {
- my ($interfaces, $ifname) = @_;
-
- my $count = grep { $_ eq $ifname } values %$interfaces;
- return ($count == 0);
-}
-
-# Find next available interface name
-sub find_available {
- my ($interfaces, $ifprefix) = @_;
- $ifprefix =~ s/\d+$//;
-
- for (my $id = 0; ; $id++) {
- my $ifname = sprintf("%s%d", $ifprefix, $id);
-
- # is it in Vyatta config?
- return $ifname if (is_available($interfaces, $ifname));
- }
-}
-
-# Find the hardware id in the parsed config node for interface
-sub get_hwid_from_children {
- my $children = shift;
-
- foreach my $attr (@$children) {
- next unless (($attr->{'name'} =~ /^hw-id ([0-9a-f:]+)/) || ($attr->{'name'} =~ /^hw-id "([0-9a-f:]+)"/));
- return $1;
- }
-
- return; # not found
-}
-
-
-# Leave file for vyatta_interface_rescan
-sub leave_rescan_hint {
- my ($ifname, $hwaddr) = @_;
- my $name = "$VYATTAUDEV/$ifname";
-
- mkdir($VYATTAUDEV);
- open (my $f, '>', $name)
- or die "Can't create $name : $!";
-
- print {$f} "$hwaddr\n";
- close $f;
- return 1;
-}
-
-# Use biosdevname program (ethernet only)
-# to try and find name based on PCI slot and DMI info
-sub biosdevname {
- my $ifname = shift;
-
- # biosdevname works only on ethernet devices
- return $ifname unless ($ifname =~ /^eth/);
-
- # Don't use biosdevname in Xen
- return $ifname if ( -d "/proc/xen" );
-
- # Let the interface name changes ordered by previous invocations of this
- # script complete before we call biosdevname. If we don't, biosdevame
- # may generate incorrect name.
- sleep 1;
-
- my $biosname = `/sbin/biosdevname --policy all_ethN -i $ifname 2>/dev/null`;
- chomp $biosname;
-
- # if biosdevname has no answer it outputs a nothing
- return ($biosname eq '') ? $ifname : $biosname;
-}
-
-# parse vyatta config.boot
-# if file does not then running before off livecd then return empty hash
-sub parse_config_boot {
- my $interfaces = {};
-
- if ( -f $BOOTFILE ) {
- my $xcp = new XorpConfigParser();
- $xcp->parse($BOOTFILE);
-
- my $inode = $xcp->get_node(['interfaces']);
- if ($inode) {
- foreach my $child (@{$inode->{'children'}}) {
- # is hwid defined in config?
- my $hwid = get_hwid_from_children($child->{'children'});
- next unless $hwid;
-
- # split into type 'ethernet' and 'eth0'
- my ($type, $intf) = ($child->{'name'} =~ /^(\w+) (\w+)/);
- next unless defined($type);
- next unless ($type eq 'ethernet') || ($type eq 'wireless');
-
- $interfaces->{$hwid} = $intf;
- }
- }
- }
-
- return $interfaces;
-}
-
-sub logit {
- my ($log, $msg) = @_;
- my $now = localtime;
- print $log "$now: $msg";
-}
-
-# Determine network name to use based on Vyatta config during boot
-sub coldplug {
- my ($ifname, $hwaddr, $predef_ifname) = @_;
-
- # at this time root directory is read-only so use log file instead
- mkdir ($UDEVLOG);
- open (my $log, '>>', $LOGFILE)
- or die "Can't open $LOGFILE : $!";
- logit($log, "lookup $ifname $hwaddr\n");
-
- # parse config file to produce map of existing hw-id values
- my $interfaces = parse_config_boot();
-
- # is name already in config file
- my $newname = $interfaces->{$hwaddr};
- if ($newname) {
- logit($log, "use hw-id $hwaddr in config mapped to '$newname'\n");
- return $newname;
- }
-
- # add already assigned names
- if (opendir(my $dir, $VYATTAUDEV)) {
- foreach my $intf (grep { ! /^\./ } readdir($dir)) {
- if (open (my $f, '<', "$VYATTAUDEV/$intf")) {
- my $hwid = <$f>;
- close $f;
- chomp $hwid;
-
- $interfaces->{$hwid} = $intf;
- }
- }
- }
-
- if ($predef_ifname) {
- $newname = $predef_ifname;
- logit($log, "predefined interface name for $ifname returned '$newname'\n");
- }
- else {
- $newname = biosdevname($ifname);
- logit($log, "biosdevname for $ifname returned '$newname'\n");
- }
-
- unless (is_available($interfaces, $newname)) {
- $newname = find_available($interfaces, $newname);
- }
-
- logit($log, "new name for '$ifname' is '$newname'\n");
- close $log;
-
- leave_rescan_hint($newname, $hwaddr);
-
- return $newname;
-}
-
-# Determine name from active config
-sub hotplug {
- my ($ifname, $hwaddr, $predef_ifname) = @_;
-
- # real filesystem available use real logging
- openlog("vyatta-net-name", "", LOG_DAEMON);
-
- # Parse active config
- my $cfg = new Vyatta::Config;
- $cfg->setLevel('interfaces');
-
- my $interfaces = {};
- foreach my $type ($cfg->listOrigNodes()) {
- next unless ($type eq 'ethernet') || ($type eq 'wireless');
- foreach my $intf ($cfg->listOrigNodes($type)) {
- my $hwid = $cfg->returnOrigValue("$type $intf hw-id");
- next unless $hwid;
- # TBD this could be a hash with name and path?
- $interfaces->{$hwid} = $intf;
- }
- }
-
- my $newname = $interfaces->{$hwaddr};
- if ($newname) {
- syslog(LOG_DEBUG, "use hw-id %s in config mapped to '%s'", $hwaddr, $newname);
- return $newname;
- }
-
- if ($predef_ifname) {
- $newname = $predef_ifname;
- syslog(LOG_DEBUG, "predefined interface name for %s returned '%s'", $ifname, $newname);
- }
- else{
- $newname = biosdevname($ifname);
- syslog(LOG_DEBUG, "biosdevname for %s returned '%s'", $ifname, $newname);
- }
-
- unless (is_available($interfaces, $newname)) {
- $newname = find_available($interfaces, $newname);
- }
-
- syslog(LOG_INFO, "new name for '%s' is '%s'", $ifname, $newname);
-
- return $newname;
-}
-
-my $LOCKF;
-sub lock_file {
- open ($LOCKF, '>', $LOCKFILE)
- or die "Can't open $LOCKFILE : $!";
-
- flock ($LOCKF, LOCK_EX)
- or die "Can't lock $LOCKFILE : $!";
-
-}
-
-sub unlock_file {
- close $LOCKF;
- $LOCKF = undef;
-}
-
-# This script is called from udev with two or three arguments
-# it outputs the new name (if any) to stdout
-if ($#ARGV > 2 or $#ARGV < 1) {
- die "vyatta_net_name called with wrong args:" . join(' ', @ARGV) . "\n";
-}
-
-my $ifname = $ARGV[0];
-my $hwaddr = $ARGV[1];
-
-my $predef_ifname = "";
-if ($ARGV[2]){
- $predef_ifname = $ARGV[2];
-}
-
-lock_file;
-my $newname;
-if ( -d $VYATTACFG ) {
- $newname = hotplug($ifname, $hwaddr, $predef_ifname);
-} else {
- $newname = coldplug($ifname, $hwaddr, $predef_ifname);
-}
-unlock_file;
-
-print "$newname\n" if ($newname);
-
-exit 0;