summaryrefslogtreecommitdiff
path: root/lib/Vyatta/Misc.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Vyatta/Misc.pm')
-rwxr-xr-xlib/Vyatta/Misc.pm588
1 files changed, 0 insertions, 588 deletions
diff --git a/lib/Vyatta/Misc.pm b/lib/Vyatta/Misc.pm
deleted file mode 100755
index 001fc93..0000000
--- a/lib/Vyatta/Misc.pm
+++ /dev/null
@@ -1,588 +0,0 @@
-# Module: VyattaMisc.pm
-#
-# Author: Marat <marat@vyatta.com>
-# Date: 2007
-# Description: Implements miscellaneous commands
-
-# **** 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.
-#
-# This code was originally developed by Vyatta, Inc.
-# Portions created by Vyatta are Copyright (C) 2006, 2007, 2008 Vyatta, Inc.
-# All Rights Reserved.
-# **** End License ****
-
-package Vyatta::Misc;
-use strict;
-
-require Exporter;
-
-our @ISA = qw(Exporter);
-our @EXPORT = qw(getInterfaces getIP getNetAddIP get_sysfs_value
- is_address_enabled is_dhcp_enabled get_ipaddr_intf_hash
- isIpAddress is_ip_v4_or_v6 interface_description
- is_local_address is_primary_address get_ipnet_intf_hash
- isValidPortNumber get_terminal_size get_terminal_height
- get_terminal_width is_port_available );
-our @EXPORT_OK = qw(generate_dhclient_intf_files
- getInterfacesIPadresses
- getPortRuleString
- get_short_config_path);
-
-use Vyatta::Config;
-use Vyatta::Interface;
-use NetAddr::IP;
-use Socket;
-Socket6->import(qw(inet_pton getaddrinfo));
-
-#
-# returns a hash of ipaddrs => interface
-#
-# only works for ipv4
-#
-sub get_ipaddr_intf_hash {
- my %config_ipaddrs = ();
- my @lines = `ip addr show | grep 'inet '`;
- chomp @lines;
- foreach my $line (@lines) {
- if ($line =~ /vtun|wan/) {
- if ($line =~ /inet\s+([0-9.]+).*\s([\w.]+)$/) {
- $config_ipaddrs{$1} = $2;
- }
- } else {
- if ($line =~ /inet\s+([0-9.]+)\/.*\s([\w.]+)$/) {
- $config_ipaddrs{$1} = $2;
- }
- }
- }
-
- return \%config_ipaddrs;
-}
-
-#
-# returns a hash of ipnet => interface
-#
-# works for both ipv4 and ipv6
-#
-sub get_ipnet_intf_hash {
- my @args = qw(ip addr show);
- my @addresses;
- my %config_ipaddrs = ();
-
- open my $ipcmd, '-|'
- or exec @args
- or die "ip addr command failed: $!";
-
- my $iface = "";
- while (<$ipcmd>) {
- my ( $proto, $addr ) = split;
- if ( $proto =~ /.*:$/ && $addr =~ /.*:$/) {
- $iface = $addr;
- chop($iface);
- }
- next unless ( $proto =~ /inet/ );
- $config_ipaddrs{$addr} = $iface;
- }
- close $ipcmd;
-
- return \%config_ipaddrs;
-}
-
-
-# Check whether an address is the primary address on some interface
-sub is_primary_address {
- my $ip_address = shift;
-
- my $ref = get_ipaddr_intf_hash();
- my %hash = %{$ref};
- if (!defined $hash{$ip_address}) {
- return;
- }
-
- my $line = `ip address show $hash{$ip_address} | grep 'inet' | head -n 1`;
- chomp($line);
- my $primary_address = undef;
-
- if ($line =~ /vtun|wan/) {
- if ($line =~ /inet\s+([0-9.]+).*\s([\w.]+)$/) {
- $primary_address = $1;
- }
- } else {
- if ($line =~ /inet\s+([0-9.]+)\/.*\s([\w.]+)$/) {
- $primary_address = $1;
- }
- }
-
- return 1 if ($ip_address eq $primary_address);
- return;
-}
-
-# remove '/opt/vyatta/etc' from begining of config directory path
-sub get_short_config_path {
- my $cfg_path = shift;
- my $shortened_cfg_path = "";
- $shortened_cfg_path = $cfg_path if defined $cfg_path;
- $shortened_cfg_path =~ s/^\/opt\/vyatta\/etc//;
-
- return $shortened_cfg_path;
-}
-
-sub get_sysfs_value {
- my ( $intf, $name ) = @_;
-
- open( my $statf, '<', "/sys/class/net/$intf/$name" )
- or die "Can't open statistics file /sys/class/net/$intf/$name";
-
- my $value = <$statf>;
- chomp $value if defined $value;
- close $statf;
-
- return $value;
-}
-
-# check if interface is configured to get an IP address using dhcp
-sub is_dhcp_enabled {
- my ( $name, $outside_cli ) = @_;
- my $intf = new Vyatta::Interface($name);
- return unless $intf;
-
- my $config = new Vyatta::Config;
-
- $config->setLevel( $intf->path() );
- # the "effective" observers can be used both inside and outside
- # config sessions.
- foreach my $addr ( $config->returnEffectiveValues('address') ) {
- return 1 if ( $addr && $addr eq "dhcp" );
- }
-
- return;
-}
-
-# check if any non-dhcp addresses configured
-sub is_address_enabled {
- my $name = shift;
- my $intf = new Vyatta::Interface($name);
- $intf or return;
-
- my $config = new Vyatta::Config;
- $config->setLevel( $intf->path() );
- foreach my $addr ( $config->returnOrigValues('address') ) {
- return 1 if ( $addr && $addr ne 'dhcp' );
- }
-
- return;
-}
-
-# return dhclient related files for interface
-sub generate_dhclient_intf_files {
- my $intf = shift;
- my $dhclient_dir = '/run/dhclient/';
-
- $intf =~ s/\./_/g;
- my $intf_config_file = $dhclient_dir . 'dhclient_' . $intf . '.conf';
- my $intf_process_id_file = $dhclient_dir . 'dhclient_' . $intf . '.pid';
- my $intf_leases_file = $dhclient_dir . 'dhclient_' . $intf . '.leases';
-
- return ( $intf_config_file, $intf_process_id_file, $intf_leases_file );
-}
-
-# get list of interfaces on the system via sysfs
-# skip dot files (and any interfaces name .xxx)
-# and bond_masters file used by bonding
-# and wireless control interfaces
-sub getInterfaces {
- opendir( my $sys_class, '/sys/class/net' )
- or die "can't open /sys/class/net: $!";
- my @interfaces = grep { ( !/^\./ ) &&
- ( $_ ne 'bonding_masters' ) &&
- !( $_ =~ '^mon.wlan\d$') &&
- !( $_ =~ '^wmaster\d+$')
- } readdir $sys_class;
- closedir $sys_class;
-
- return @interfaces;
-}
-
-# Test if IP address is local to the system.
-# Implemented by doing bind since by default
-# Linux will only allow binding to local addresses
-sub is_local_address {
- my $addr = shift;
- my $ip = new NetAddr::IP $addr;
- die "$addr: not a valid IP address"
- unless $ip;
-
- my ($pf, $sockaddr);
- if ($ip->version() == 4) {
- $pf = PF_INET;
- $sockaddr = sockaddr_in(0, $ip->aton());
- } else {
- $pf = PF_INET6;
- $sockaddr = sockaddr_in6(0, $ip->aton());
- }
-
- socket( my $sock, $pf, SOCK_STREAM, 0)
- or die "socket failed\n";
-
- return bind($sock, $sockaddr);
-}
-
-# Test if the given port is currently in use by attempting
-# to bind to it, success shows the port is currently free.
-sub is_port_available {
- my $port = shift;
- my $family = PF_INET;
- my $sockaddr = sockaddr_in($port, INADDR_ANY);
- my $proto = getprotobyname('tcp');
-
- socket(my $sock, $family, SOCK_STREAM, $proto)
- or die "socket failed\n";
-
- return bind($sock, $sockaddr);
-}
-
-# get list of IPv4 and IPv6 addresses
-# if name is defined then get the addresses on that interface
-# if type is defined then restrict to that type (inet, inet6)
-sub getIP {
- my ( $name, $type ) = @_;
- my @args = qw(ip addr show);
- my @addresses;
-
- push @args, ('dev', $name) if $name;
-
- open my $ipcmd, '-|'
- or exec @args
- or die "ip addr command failed: $!";
-
- <$ipcmd>;
- while (<$ipcmd>) {
- my ( $proto, $addr ) = split;
- next unless ( $proto =~ /inet/ );
- if ($type) {
- next if ( $proto eq 'inet6' && $type != 6 );
- next if ( $proto eq 'inet' && $type != 4 );
- }
-
- push @addresses, $addr;
- }
- close $ipcmd;
-
- return @addresses;
-}
-
-my %type_hash = (
- 'broadcast' => 'is_broadcast',
- 'multicast' => 'is_multicast',
- 'pointtopoint' => 'is_pointtopoint',
- 'loopback' => 'is_loopback',
- );
-
-# getInterfacesIPadresses() returns IPv4 addresses for the interface type
-# possible type of interfaces : 'broadcast', 'pointtopoint', 'multicast', 'all'
-# and 'loopback'
-sub getInterfacesIPadresses {
- my $type = shift;
- my $type_func;
- my @ips;
-
- $type or die "Interface type not defined";
-
- if ( $type ne 'all' ) {
- $type_func = $type_hash{$type};
- die "Invalid type specified to retreive IP addresses for: $type"
- unless $type_func;
- }
-
- foreach my $name ( getInterfaces() ) {
- my $intf = new Vyatta::Interface($name);
- next unless $intf;
- if ( defined $type_func ) {
- next unless $intf->$type_func();
- }
-
- my @addresses = $intf->address(4);
- push @ips, @addresses;
- }
-
- return @ips;
-}
-
-sub getNetAddrIP {
- my $name = shift;
- my $intf = new Vyatta::Interface($name);
- $intf or return;
-
- foreach my $addr ( $intf->addresses() ) {
- my $ip = new NetAddr::IP $addr;
- next unless ( $ip && ip->version() == 4 );
- return $ip;
- }
-
- return;
-}
-
-sub is_ip_v4_or_v6 {
- my $addr = shift;
-
- my $ip = new NetAddr::IP $addr;
- return unless defined $ip;
-
- my $vers = $ip->version();
- if ( $vers == 4 ) {
- # NetAddr::IP will accept short forms 1.1 and hostnames
- # so check if all 4 octets are defined
- return 4 unless ( $addr !~ /\d+\.\d+\.\d+\.\d+/ ); # undef
- }
- elsif ( $vers == 6 ) {
- return 6;
- }
-
- return;
-}
-
-sub isIpAddress {
- my $ip = shift;
-
- return unless $ip =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/;
-
- return unless ( $1 > 0 && $1 < 256 );
- return unless ( $2 >= 0 && $2 < 256 );
- return unless ( $3 >= 0 && $3 < 256 );
- return unless ( $4 >= 0 && $4 < 256 );
- return 1;
-}
-
-sub isClusterIP {
- my ( $vc, $ip ) = @_;
-
- return unless $ip; # undef
-
- my @cluster_groups = $vc->listNodes('cluster group');
- foreach my $cluster_group (@cluster_groups) {
- my @services = $vc->returnValues("cluster group $cluster_group service");
- foreach my $service (@services) {
- if ($service =~ /\//) {
- $service = substr( $service, 0, index( $service, '/' ));
- }
- if ( $ip eq $service ) {
- return 1;
- }
- }
- }
-
- return;
-}
-
-sub remove_ip_prefix {
- my @addr_nets = @_;
-
- s/\/\d+$// for @addr_nets;
- return @addr_nets;
-}
-
-sub is_ip_in_list {
- my ( $ip, @list ) = @_;
-
- @list = remove_ip_prefix(@list);
- my %list_hash = map { $_ => 1 } @list;
-
- return $list_hash{$ip};
-}
-
-sub isIPinInterfaces {
- my ( $vc, $ip_addr, @interfaces ) = @_;
-
- return unless $ip_addr; # undef == false
-
- foreach my $name (@interfaces) {
- return 1 if ( is_ip_in_list( $ip_addr, getIP($name) ) );
- }
-
- return; # false (undef)
-}
-
-sub isClusteringEnabled {
- my ($vc) = @_;
-
- return $vc->exists('cluster');
-}
-
-# $str: string representing a port number
-# returns ($success, $err)
-# $success: 1 if success. otherwise undef
-# $err: error message if failure. otherwise undef
-sub isValidPortNumber {
- my $str = shift;
- return ( undef, "\"$str\" is not a valid port number" )
- if ( !( $str =~ /^\d+$/ ) );
- return ( undef, "invalid port \"$str\" (must be between 1 and 65535)" )
- if ( $str < 1 || $str > 65535 );
- return ( 1, undef );
-}
-
-# $str: string representing a port range
-# $sep: separator for range
-# returns ($success, $err)
-# $success: 1 if success. otherwise undef
-# $err: error message if failure. otherwise undef
-sub isValidPortRange {
- my $str = shift;
- my $sep = shift;
- return ( undef, "\"$str\" is not a valid port range" )
- if ( !( $str =~ /^(\d+)$sep(\d+)$/ ) );
- my ( $start, $end ) = ( $1, $2 );
- my ( $success, $err ) = isValidPortNumber($start);
- return ( undef, $err ) if ( !defined($success) );
- ( $success, $err ) = isValidPortNumber($end);
- return ( undef, $err ) if ( !defined($success) );
- return ( undef, "invalid port range ($end is not greater than $start)" )
- if ( $end <= $start );
- return ( 1, undef );
-}
-
-# $str: string representing a port name
-# $proto: protocol to check
-# returns ($success, $err)
-# $success: 1 if success. otherwise undef
-# $err: error message if failure. otherwise undef
-sub isValidPortName {
- my $str = shift;
- my $proto = shift;
- return ( undef, "\"\" is not a valid port name for protocol \"$proto\"" )
- if ( $str eq '' );
-
- my $port = getservbyname( $str, $proto );
- return ( 1, undef ) if $port;
-
- return ( undef, "\"$str\" is not a valid port name for protocol \"$proto\"" );
-}
-
-sub getPortRuleString {
- my $port_str = shift;
- my $can_use_port = shift;
- my $prefix = shift;
- my $proto = shift;
- my $negate = '';
- if ( $port_str =~ /^!(.*)$/ ) {
- $port_str = $1;
- $negate = '! ';
- }
- $port_str =~ s/(\d+)-(\d+)/$1:$2/g;
-
- my $num_ports = 0;
- my @port_specs = split /,/, $port_str;
- foreach my $port_spec (@port_specs) {
- my ( $success, $err ) = ( undef, undef );
- if ( $port_spec =~ /:/ ) {
- ( $success, $err ) = isValidPortRange( $port_spec, ':' );
- if ( defined($success) ) {
- $num_ports += 2;
- next;
- }
- else {
- return ( undef, $err );
- }
- }
- if ( $port_spec =~ /^\d/ ) {
- ( $success, $err ) = isValidPortNumber($port_spec);
- if ( defined($success) ) {
- $num_ports += 1;
- next;
- }
- else {
- return ( undef, $err );
- }
- }
- if ($proto eq 'tcp_udp') {
- ( $success, $err ) = isValidPortName( $port_spec, 'tcp' );
- if (defined $success) {
- # only do udp test if the tcp test was a success
- ( $success, $err ) = isValidPortName( $port_spec, 'udp' )
- }
- } else {
- ( $success, $err ) = isValidPortName( $port_spec, $proto );
- }
- if ( defined($success) ) {
- $num_ports += 1;
- next;
- }
- else {
- return ( undef, $err );
- }
- }
-
- my $rule_str = '';
- if ( ( $num_ports > 0 ) && ( !$can_use_port ) ) {
- return ( undef, "ports can only be specified when protocol is \"tcp\" "
- . "or \"udp\" (currently \"$proto\")" );
- }
- if ( $num_ports > 15 ) {
- return ( undef, "source/destination port specification only supports "
- . "up to 15 ports (port range counts as 2)" );
- }
- if ( $num_ports > 1 ) {
- $rule_str = " -m multiport $negate --${prefix}ports ${port_str}";
- }
- elsif ( $num_ports > 0 ) {
- $rule_str = " $negate --${prefix}port ${port_str}";
- }
-
- return ( $rule_str, undef );
-}
-
-sub interface_description {
- my $name = shift;
-
- open my $ifalias, '<', "/sys/class/net/$name/ifalias"
- or return;
-
- my $description = <$ifalias>;
- close $ifalias;
-
- # If the interface has a description set then just use that, if not then check
- # the active config to see if one is configured there. Used for interfaces
- # that can be destroyed and recreated during opertion, but then don't have
- # their description reset.
-
- if ($description){
- chomp $description;
- } else {
- my $intf = new Vyatta::Interface($name);
- my $config = new Vyatta::Config;
-
- $config->setLevel( $intf->path() );
-
- if ($config->existsOrig('description')) {
- $description = $config->returnOrigValue('description');
- }
- }
-
- return $description;
-}
-
-# returns (rows, columns) for terminal size
-sub get_terminal_size {
- return Vyatta::ioctl::get_terminal_size();
-}
-
-# return only terminal width
-sub get_terminal_width {
- my ($rows, $cols) = get_terminal_size;
- return $cols;
-}
-
-# return only terminal height
-sub get_terminal_height {
- my ($rows, $cols) = get_terminal_size;
- return $rows;
-}
-
-1;