#! /usr/bin/perl

#
# Copyright (c) 2018-2019 AT&T Intellectual Property.
# Copyright (c) 2014-2017 by Brocade Communications Systems, Inc.
# Copyright (c) 2007-2010 Vyatta, Inc.
# All rights reserved.
#
# SPDX-License-Identifier: GPL-2.0-only
#

use strict;
use warnings;
use Getopt::Long;
use POSIX qw(strtol);
use Vyatta::IFMib qw(get_descr);

# This is used to show values corresponding to to results IF-MIB.
my %interfaces;

sub show_ifindex {
    foreach my $ifname (@_) {
        my $info    = $interfaces{$ifname};
        my $ifindex = $info->{'ifIndex'};
        printf "%s: ifIndex = %d\n", $ifname, $ifindex;
    }
}

sub show_ifalias {
    foreach my $ifname (@_) {
        my $info    = $interfaces{$ifname};
        my $ifalias = $info->{'ifAlias'};
        printf "%s: ifAlias = %s\n", $ifname,
          defined($ifalias) ? $ifalias : $ifname;
    }
}

sub read_sysfs {
    my $filename = shift;

    open( my $f, '<', $filename )
      or return;    # not a PCI device

    my $val = <$f>;
    close $f;

    return strtol($val);
}

# Imitate code in net-snmp to lookup PC
# TODO - move to common code extension (and handle USB?)
sub pci_info {
    my $ifname    = shift;
    my $vendor_id = read_sysfs("/sys/class/net/$ifname/device/vendor");
    my $device_id = read_sysfs("/sys/class/net/$ifname/device/device");

    return unless ( defined($vendor_id) && defined($device_id) );

    my $cmd = sprintf("lspci -m -d %04x:%04x", $vendor_id, $device_id);
    open( my $pci, '-|', $cmd )
      or die "Can't run $cmd";
    my $info = <$pci>;
    close $pci;

    return unless $info;

    # extract vendor and device description from output
    $info =~ /^\S+ "[^"]*" "([^"]*)" "([^"]*)"/;

    return "$1 $2";
}

sub show_ifdescr {
    foreach my $ifname (@_) {
        my $ifdescr = get_descr($ifname);

        printf "%s: ifDescr = %s\n", $ifname,
		defined($ifdescr) ? $ifdescr : $ifname;
    }
}

sub show_all {
    foreach my $ifname (@_) {
        my $info    = $interfaces{$ifname};
        my $ifindex = $info->{'ifIndex'};
        my $ifalias = $info->{'ifAlias'};
        my $ifdescr = pci_info($ifname);

        printf "%s: ifIndex = %d\n", $ifname, $ifindex;

        my $pad = sprintf( "%-*s", length($ifname) + 1, " " );
        printf "%s ifAlias = %s\n", $pad, $ifalias if ($ifalias);
        printf "%s ifDescr = %s\n", $pad, $ifdescr if ($ifdescr);
    }
}

my $show = \&show_all;

GetOptions(
    "ifindex" => sub { $show = \&show_ifindex },
    "ifalias" => sub { $show = \&show_ifalias },
    "ifdescr" => sub { $show = \&show_ifdescr },
) or die "Unknown option\n";

# List of all interfaces that currently exist on system
# includes interfaces that may be outside Vyatta CLI because
# they still show up in SNMP
open( my $ip, '-|', 'ip li' )
  or die "Can't run ip command\n";

my $ifname;
while (<$ip>) {
    if (/^(\d+): ([^:]*): /) {
        $ifname = $2;
        $interfaces{$ifname} = { 'ifIndex' => $1 };
    }
    elsif (/^ +alias (.*)$/) {
        $interfaces{$ifname}->{'ifAlias'} = $1;
    }
}
close $ip;

if (@ARGV) {
    $show->(@ARGV);
}
else {
    $show->( sort keys %interfaces );
}
