summaryrefslogtreecommitdiff
path: root/scripts/snmp/vyatta-snmp.pl
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/snmp/vyatta-snmp.pl')
-rwxr-xr-xscripts/snmp/vyatta-snmp.pl333
1 files changed, 333 insertions, 0 deletions
diff --git a/scripts/snmp/vyatta-snmp.pl b/scripts/snmp/vyatta-snmp.pl
new file mode 100755
index 00000000..5c4ff1d0
--- /dev/null
+++ b/scripts/snmp/vyatta-snmp.pl
@@ -0,0 +1,333 @@
+#!/usr/bin/perl
+#
+# Module: vyatta-snmp.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.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc.
+# All Rights Reserved.
+#
+# Author: Stig Thormodsrud
+# Date: October 2007
+# Description: Script to glue vyatta cli to snmp daemon
+#
+# **** End License ****
+#
+
+use strict;
+use warnings;
+
+use lib "/opt/vyatta/share/perl5/";
+use Vyatta::Config;
+use Vyatta::Misc;
+use NetAddr::IP;
+use Getopt::Long;
+use File::Copy;
+use Socket;
+use Socket6;
+
+my $mibdir = '/opt/vyatta/share/snmp/mibs';
+my $snmp_start = 'systemctl start snmpd.service';
+my $snmp_stop = 'systemctl stop snmpd.service';
+my $snmp_conf = '/etc/snmp/snmpd.conf';
+my $snmp_client = '/etc/snmp/snmp.conf';
+my $snmp_tmp = "/tmp/snmpd.conf.$$";
+my $snmp_snmpv3_user_conf = '/usr/share/snmp/snmpd.conf';
+my $snmp_snmpv3_createuser_conf = '/var/lib/snmp/snmpd.conf';
+my $versionfile = '/opt/vyatta/etc/version';
+my $local_agent = 'unix:/run/snmpd.socket';
+my $password_file = '/config/snmp/superuser_pass';
+
+my $snmp_level = 'service snmp';
+
+sub snmp_running {
+ open (my $pidf, '<', "/run/snmpd.pid")
+ or return;
+ my $pid = <$pidf>;
+ close $pidf;
+
+ chomp $pid;
+ my $exe = readlink "/proc/$pid/exe";
+
+ return (defined($exe) && $exe eq "/usr/sbin/snmpd");
+}
+
+sub snmp_stop {
+ system("$snmp_stop > /dev/null 2>&1");
+}
+
+sub snmp_start {
+ # we must stop snmpd first for creating vyatta user
+ system("$snmp_stop > /dev/null 2>&1");
+ open (my $fh, '>', $snmp_tmp)
+ or die "Couldn't open $snmp_tmp - $!";
+
+ select $fh;
+ snmp_get_constants();
+ snmp_get_values();
+ snmp_get_traps();
+ close $fh;
+ select STDOUT;
+
+ snmp_client_config();
+
+ move($snmp_tmp, $snmp_conf)
+ or die "Couldn't move $snmp_tmp to $snmp_conf - $!";
+}
+
+sub get_version {
+ my $version = "unknown-version";
+
+ if (open (my $f, '<', $versionfile)) {
+ while (<$f>) {
+ chomp;
+ if (m/^Version\s*:\s*(.*)$/) {
+ $version = $1;
+ last;
+ }
+ }
+ close $f;
+ }
+ return $version;
+}
+
+# convert address to snmpd transport syntax
+sub transport_syntax {
+ my ($addr, $port) = @_;
+ my $ip = new NetAddr::IP $addr;
+ die "$addr: not a valid IP address" unless $ip;
+
+ my $version = $ip->version();
+ return "udp:$addr:$port" if ($version == 4);
+ return "udp6:[$addr]:$port" if ($version == 6);
+ die "$addr: unknown IP version $version";
+}
+
+# Test if IPv6 is possible by opening a socket
+sub ipv6_disabled {
+ socket ( my $s, PF_INET6, SOCK_DGRAM, 0)
+ or return 1;
+ close($s);
+ return;
+}
+
+# Find SNMP agent listening addresses
+sub get_listen_address {
+ my $config = new Vyatta::Config;
+ my @listen;
+
+ $config->setLevel('service snmp listen-address');
+ my @address = $config->listNodes();
+
+ if(@address) {
+ foreach my $addr (@address) {
+ my $port = $config->returnValue("$addr port");
+ push @listen, transport_syntax($addr, $port);
+ }
+ } else {
+ # default if no address specified
+ @listen = ( 'udp:161' );
+ push @listen, 'udp6:161' unless ipv6_disabled();
+ return @listen;
+ }
+
+ return @listen;
+}
+
+sub snmp_get_constants {
+ my $version = get_version();
+ my $now = localtime;
+ my @addr = get_listen_address();
+
+ # add local unix domain target for use by operational commands
+ unshift @addr, $local_agent;
+
+ print "# autogenerated by vyatta-snmp.pl on $now\n";
+ print "sysDescr VyOS $version\n";
+ print "sysObjectID 1.3.6.1.4.1.44641\n";
+ print "sysServices 14\n";
+ print "master agentx\n"; # maybe needed by lldpd
+ print "agentaddress ", join(',',@addr), "\n";
+ print "agentXPerms 0755 0755\n";
+
+ # add hook to read IF-MIB::ifAlias from sysfs
+ print "pass .1.3.6.1.2.1.31.1.1.1.18 /opt/vyatta/sbin/if-mib-alias\n";
+
+ print "smuxpeer .1.3.6.1.4.1.3317.1.2.2\n"; # ospfd
+ print "smuxpeer .1.3.6.1.4.1.3317.1.2.5\n"; # bgpd
+ print "smuxpeer .1.3.6.1.4.1.3317.1.2.3\n"; # ripd
+ print "smuxpeer .1.3.6.1.4.1.3317.1.2.9\n"; # mribd
+ print "smuxpeer .1.3.6.1.2.1.83\n"; # mribd
+ print "smuxpeer .1.3.6.1.4.1.3317.1.2.8\n"; # pimd
+ print "smuxpeer .1.3.6.1.2.1.157\n"; # pimd
+ print "smuxsocket localhost\n";
+}
+
+# generate a random character hex string
+sub randhex {
+ my $length = shift;
+ return join "", map { unpack "H*", chr(rand(256)) } 1..($length/2);
+}
+
+# output snmpd.conf file syntax for community
+sub print_community {
+ my ($config, $community) = @_;
+ my $ro = $config->returnValue('authorization');
+ $ro = 'ro' unless $ro;
+
+ my @clients = $config->returnValues('client');
+ my @networks = $config->returnValues('network');
+
+ my @restriction = (@clients, @networks);
+ if (!@restriction) {
+ print $ro . "community $community\n";
+ print $ro . "community6 $community\n" unless ipv6_disabled();
+ return;
+ }
+
+ foreach my $addr (@restriction) {
+ my $ip = new NetAddr::IP $addr;
+ die "$addr: Not a valid IP address" unless $ip;
+
+ if ($ip->version() == 4) {
+ print $ro . "community $community $addr\n";
+ } elsif ($ip->version() == 6) {
+ print $ro . "community6 $community $addr\n";
+ } else {
+ die "$addr: bad IP version ", $ip->version();
+ }
+ }
+}
+
+sub snmp_get_values {
+ my $config = new Vyatta::Config;
+
+ my @communities = $config->listNodes("service snmp community");
+ foreach my $community (@communities) {
+ $config->setLevel("service snmp community $community");
+ print_community($config, $community);
+ }
+
+ $config->setLevel("service snmp smux-peer");
+ my @smuxpeers = $config->returnValues();
+ foreach my $smuxpeer (@smuxpeers) {
+ print "smuxpeer $smuxpeer \n";
+ }
+
+ $config->setLevel($snmp_level);
+ my $contact = $config->returnValue("contact");
+ if (defined $contact) {
+ print "SysContact $contact \n";
+ }
+
+ my $description = $config->returnValue("description");
+ if (defined $description) {
+ print "SysDescr $description \n";
+ }
+
+ my $location = $config->returnValue("location");
+ if (defined $location) {
+ print "SysLocation $location \n";
+ }
+}
+
+sub snmp_get_traps {
+ my $config = new Vyatta::Config;
+ $config->setLevel($snmp_level);
+
+ # linkUp/Down configure the Event MIB tables to monitor
+ # the ifTable for network interfaces being taken up or down
+ # for making internal queries to retrieve any necessary information
+
+ # create an internal snmpv3 user of the form 'vyattaxxxxxxxxxxxxxxxx'
+ my $vyatta_user = "vyatta" . randhex(16);
+ snmp_create_snmpv3_user($vyatta_user);
+ snmp_write_snmpv3_user($vyatta_user);
+ print "iquerySecName $vyatta_user\n";
+
+ # Modified from the default linkUpDownNotification
+ # to include more OIDs and poll more frequently
+ print <<EOF;
+notificationEvent linkUpTrap linkUp ifIndex ifDescr ifType ifAdminStatus ifOperStatus
+notificationEvent linkDownTrap linkDown ifIndex ifDescr ifType ifAdminStatus ifOperStatus
+monitor -r 10 -e linkUpTrap "Generate linkUp" ifOperStatus != 2
+monitor -r 10 -e linkDownTrap "Generate linkDown" ifOperStatus == 2
+EOF
+
+ my @trap_targets = $config->listNodes("trap-target");
+ return unless @trap_targets;
+
+ foreach my $trap_target (@trap_targets) {
+ my $port = $config->returnValue("trap-target $trap_target port");
+ my $community
+ = $config->returnValue("trap-target $trap_target community");
+
+ print "trap2sink $trap_target";
+ print ":$port" if $port;
+ print " $community" if $community;
+ print "\n";
+ }
+}
+
+# Configure SNMP client parameters
+sub snmp_client_config {
+ my $config = new Vyatta::Config;
+ $config->setLevel($snmp_level);
+
+ open (my $cf, '>', $snmp_client)
+ or die "Couldn't open $snmp_client - $!";
+
+ my $version = get_version();
+ my $now = localtime;
+ print {$cf} "# autogenerated by vyatta-snmp.pl on $now\n";
+
+ my $trap_source = $config->returnValue('trap-source');
+ print {$cf} "clientaddr $trap_source\n" if ($trap_source);
+ close $cf;
+}
+
+sub snmp_create_snmpv3_user {
+
+ my $vyatta_user = shift;
+ my $passphrase = randhex(32);
+
+ my $createuser = "createUser $vyatta_user MD5 \"$passphrase\" DES";
+ open(my $fh, '>', $snmp_snmpv3_createuser_conf) || die "Couldn't open $snmp_snmpv3_createuser_conf - $!";
+ print $fh $createuser;
+ close $fh;
+
+ open(my $pass_file, '>', $password_file) || die "Couldn't open $password_file - $!";
+ print $pass_file $passphrase;
+ close $pass_file;
+}
+
+sub snmp_write_snmpv3_user {
+
+ my $vyatta_user = shift;
+ my $user = "rwuser $vyatta_user\n";
+ open(my $fh, '>', $snmp_snmpv3_user_conf) || die "Couldn't open $snmp_snmpv3_user_conf - $!";
+ print $fh $user;
+ close $fh;
+}
+
+
+#
+# main
+#
+my $update_snmp;
+my $stop_snmp;
+
+GetOptions("update-snmp!" => \$update_snmp,
+ "stop-snmp!" => \$stop_snmp);
+
+snmp_start() if ($update_snmp);
+snmp_stop() if ($stop_snmp);