252N/A#
252N/A# Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
252N/A#
252N/A# ident "@(#)migration.pl 1.5 03/06/26 SMI"
252N/A#
252N/A# $Id: masfcnv,v 1.3 2004/01/09 14:04:14 rr144420 Exp $
252N/A
252N/A=head1 NAME
252N/A
252N/Amasfcnv - SNMP configuration migration script
252N/A
252N/A=head1 SYNOPSIS
252N/A
252N/Amasfcnv S<[ -cimnrs ]> S<[ -l agent|master ]> S<[ -p enable|disable|error ]>
252N/AS<[ -t none|add ]> S<[ -u agent|master|error ]> S<[ -y agent|master|error ]>
252N/A
252N/Amasfcnv [ -V ]
252N/A
252N/Amasfcnv [ -? ]
252N/A
252N/A=head1 DESCRIPTION
252N/A
252N/AThe masfcnv script is used to assist the system administrator in migrating an
252N/Aexisting set of configuration files for the Sun SNMP Management Agent for Sun
252N/AFire and Netra Systems (MASF) to the Systems Management Agent (SMA).
252N/A
252N/AThe script accepts as input the currently installed set of MASF and SMA
252N/Aconfiguration files and outputs a new set of SMA configuration files. Existing
252N/ASMA configuration files are backed up by appending ".bak" to the filename. The
252N/Aadministrator may choose to output the new configuration to the standard output
252N/Ainstead of replacing the current configuration by specifying the -n option.
252N/A
252N/AThe migration script must be run as the superuser and failure to do so will
252N/Acause the script to exit with an error message. Before running the script the
252N/Aadministrator should ensure that both the SMA and MASF agents are not running.
252N/AIf the agents are running they will be shut down by the script.
252N/A
252N/AThe migration script will install a new startup script for the MASF agent in
252N/A/etc/init.d and backup the old script. During migration, MASF will be
252N/Aconfigured as an AgentX subagent of SMA. All migration settings will be
252N/Amigrated to the SMA configuration file.
252N/A
252N/AThe migration script will abort if any unrecognised directives are found in
252N/Aeither the MASF configuration files or the SMA configuration files. This may
252N/Abe overridden with the -i option. If this option is selected, the behaviour is
252N/Ato retain unrecognised directives which were present in the SMA configuration,
252N/Abut remove those present in the MASF configuration.
252N/A
252N/AThe migration script will then proceed to migrate access control and trap
252N/Aconfiguration. As a side-effect of running the migration script, the following
252N/Adirectives may be expanded by the script into multiple directives with
252N/Aan equivalent interpretation:
252N/A
252N/A=over
252N/A
252N/A=item rwcommunity
252N/A
252N/A=item rocommunity
252N/A
252N/A=item rwuser
252N/A
252N/A=item rouser
252N/A
252N/A=item trapcommunity
252N/A
252N/A=item trapsink
252N/A
252N/A=item trap2sink
252N/A
252N/A=item informsink
252N/A
252N/A=back
252N/A
252N/A=head2 Access Control Migration
252N/A
252N/AAccess control directives will be expanded into the equivalent com2sec, group,
252N/Aaccess and view directives. Existing group names will be renamed by prepending
252N/Aa prefix to avoid conflict with any which may already be defined in SMA.
252N/A
252N/AWhen migrating SNMPv1 or v2c access control, a conflict may occur if both MASF
252N/Aand SMA configuration files have defined access permissions for the same
252N/Acommunity and source address. The default behaviour is to abort with a
252N/Amessage, unless the -y option specifies otherwise. If "-y agent" was specified
252N/Athen the MASF configuration will take precedence. If "-y master" was specified
252N/Athen the SMA configuration will be retained.
252N/A
252N/AWhen migrating USM configuration (SNMPv3), a conflict may occur if both SMA
252N/Aand MASF configurations define a user with the same securityName. If this
252N/Aoccurs then the behaviour of the script is determined by the -u option.
252N/AIf "-u agent" has been selected then the configuration of the user defined in
252N/Athe MASF configuration files will be the one that is retained. Otherwise, if
252N/Athe "-u master" option has been selected, the one defined in the SMA
252N/Aconfiguration files will be retained.
252N/A
252N/AThe migration script will by default attempt to migrate USM users from MASF to
252N/ASMA. The script will determine whether there are any existing SNMPv3 users
252N/Apresent in the SMA configuration and whether or not the default engineID has
252N/Abeen overridden in the SMA configuration files. If neither of these are found to
252N/Abe the case then the any usmUser statements containing localised
252N/Aauthentication keys can be migrated to SMA, along with the MASF engineID. This
252N/Awill result in the engineID of SMA master agent changing.
252N/A
252N/AIf the script determines that there are existing SNMPv3 users or a manually
252N/Aconfigured engineID present in the SMA configuration, then only those users
252N/Adefined in createUser statements will be transferred. Those users which were
252N/Adefined in usmUser statements will be transferred but will have their
252N/Apasswords reset to a random value. The administrator is advised to notify
252N/Atheir users of their new password and/or reset the password themselves by
252N/Aediting the newly-generated configuration file themselves.
252N/A
252N/A=head2 Trap/Inform Migration
252N/A
252N/AThe migration script will perform a check to determine whether a trap
252N/Adestination defined for MASF is already specified in an existing SMA trapsink,
252N/Atrap2sink or informsink directive. If this is the case then the directive in
252N/Athe MASF configuration will be discarded to avoid duplicate traps/informs being
252N/Areceived.
252N/A
252N/Atrapsink, trap2sink and informsink directives specified in the existing SMA
252N/Aconfiguration are considered valid destinations for MASF traps/informs and will
252N/Areceive them from the MASF subagent after migration.
252N/A
252N/AIf the "-t none" option was specified on the command line, then the migration
252N/Ascript will carry over any remaining MASF trap/inform directives without
252N/Amodification.
252N/A
252N/AIf the "-t add" option was specified (the default), then the migration script
252N/Awill expand any trapsink, trap2sink or informsink directives to use the
252N/ATARGET-MIB and NOTIFICATION-MIB. The TARGET-MIB specifies targets using IP
252N/Aaddresses, so it may be desirable to use the "-t none" option if, for example,
252N/Athe network allocates IP addresses to hostnames dynamically via DHCP.
252N/A
252N/AThe expanded directives will define filters specific to the MASF agent so that
252N/Atraps from other subagents will not be received by migrated trap destinations.
252N/AExisting filters present in the SMA configuration will by default not be
252N/Amodified and may or may not receive MASF traps depending upon the filters
252N/Awhich were originally defined for them.
252N/A
252N/AIf the -l option is specified, then any filters already defined in the
252N/ATARGET-MIB and the NOTIFICATION-MIB for SMA will be extended to include traps
252N/Afrom MASF. In the event that a trap destination is already configured in the
252N/ATARGET-MIB with the same target address and community as an existing MASF
252N/Atrap/inform sink, a conflict will arise.
252N/A
252N/AIf "-l agent" was specified and a conflict arises, then the migration script
252N/Awill use the target SNMP parameters (i.e. SNMP version and choise of
252N/Atrap/inform) defined by the MASF trap/informsink directive to send traps to
252N/Athis destination. Otherwise if the "-l master" option was specified, then the
252N/Aconflict will be resolved using the target SNMP parameters specified in the
252N/ASMA configuration.
252N/A
252N/A=head2 Miscellaneous
252N/A
252N/AIf the migration script encounters any of the following directives in the MASF
252N/Aconfiguration file and they are either not present or differ in the SMA
252N/Aconfiguration, the script will log a warning message:
252N/A
252N/A=over
252N/A
252N/A=item syslocation
252N/A
252N/A=item syscontact
252N/A
252N/A=item sysname
252N/A
252N/A=item sysservices
252N/A
252N/A=item agentgroup
252N/A
252N/A=item agentuser
252N/A
252N/A=item authtrapenable
252N/A
252N/A=back
252N/A
252N/A=head1 OPTIONS
252N/A
252N/A=over
252N/A
252N/A=item B<-?>
252N/A
252N/A=item B<--help>
252N/A
252N/ADisplays usage information.
252N/A
252N/A=item B<-c>
252N/A
252N/A=item B<--no-community>
252N/A
252N/ADo not transfer v1/v2c communities
252N/A
252N/A=item B<-i>
252N/A
252N/A=item B<--ignore-unrecognized-directives>
252N/A
252N/AContinue processing if unrecognised directives are present.
252N/A
252N/A=item B<-l> I<agent|master>
252N/A
252N/A=item B<--master-trap-target>=I<agent|master>
252N/A
252N/AIf 'agent' is specified then the existing SMA trap targets will be configured
252N/Ato receive traps that were previously sent to destinations for the Sun Fire
252N/ASNMP agent. If 'master' is specified then the targets will be configured to
252N/Areceive Sun Fire SNMP traps but existing SNMP target parameters will be used.
252N/A
252N/A=item B<-m>
252N/A
252N/A=item B<--no-usmuser>
252N/A
252N/ADo not transfer usm (v3) users
252N/A
252N/A=item B<-n>
252N/A
252N/A=item B<--dry-run>
252N/A
252N/ARun the migration without modifying any files. If any error arises then
252N/Acontinue processing. This can be used to determine the likely migration issues.
252N/A
252N/A=item B<-p> I<enable|disable|error>
252N/A
252N/A=item B<--use-agent-port>=I<enable|disable|error>
252N/A
252N/AIndicates whether the port originally used by the Sun Fire SNMP agent should be
252N/Aused by the SMA agent after migration (if the two agents are using different
252N/Aports). If 'enable' is specified then the port used by the Sun Fire SNMP agent
252N/Awill also be used by the SMA agent after migration. If 'disable' is specified
252N/Athen the ports used by SMA will not be updated by the migration tool. If
252N/Athe 'error' option is specified and the SMA agent is not already using the same
252N/Aports as those used by the original Sun Fire SNMP agent then an error will be
252N/Areported and the migration process will be terminated. If no option is
252N/Aspecified the default behaviour is equivalent to the 'error' flag.
252N/A
252N/A=item B<-r>
252N/A
252N/A=item B<--no-trap>
252N/A
252N/ADo not transfer trap destinations
252N/A
252N/A=item B<-s>
252N/A
252N/A=item B<--skip-user>
252N/A
252N/AIf a user is found in the MASF configuration file that cannot be created in the
252N/Anew configuration due to a change in the engine ID, then output a message
252N/Aindicating that the user could not be migrated (needs to be manually recreated)
252N/Aand continue processing. If this option is not present then the migration tool
252N/Awill consider such a situation as an error and abort.
252N/A
252N/A=item B<-t> I<none|add>
252N/A
252N/A=item B<--trap-filter>=I<none|add>
252N/A
252N/AIf 'none' is specified then the script will copy trap directives directly. The
252N/Aadministrator may need to manually update the configuration file to ensure
252N/Atraps are only delivered to their intended destinations. If 'add' is specifed
252N/Athen trap filters will be constructed so that traps originating from the
252N/Aoriginal Sun Fire SNMP agent are only delivered to the destinations that
252N/Aoriginally received them. 'add' is the default behaviour.
252N/A
252N/A=item B<-u> I<agent|master|error>
252N/A
252N/A=item B<--select-user>=I<agent|master|error>
252N/A
252N/ASpecifies that if a user with the same name is found in both configuration
252N/Afiles that the conflict is to be resolved using the specified configuration
252N/Afile as input. Selecting a user from a particular will also cause the group
252N/Adeclaration for that user to be taken from the same file. If 'agent' is
252N/Aspecified then the user will be taken from the configuration file for the Sun
252N/AFire SNMP Agent. If 'master' is specified then the user will be taken from the
252N/ASMA configuration. Otherwise if 'error' is given, the script will terminate.
252N/AIf this option is not present then the default behaviour is equivalent to
252N/Athe 'error' flag.
252N/A
252N/A=item B<-V>
252N/A
252N/A=item B<--version>
252N/A
252N/ADisplay the version of this script.
252N/A
252N/A=item B<-y> I<agent|master|error>
252N/A
252N/A=item B<--select-community>=I<agent|master|error>
252N/A
252N/ASpecifies that if a community and source (hostname, IP addr or range of IP
252N/Aaddresses) is found to be conflicting in the two configurations, which
252N/Acombination should be selected when mapping to a security name. If 'agent' is
252N/Aspecified then the community and source information will be taken from the
252N/Aconfiguration for the Sun Fire SNMP agent. If 'master' is specified it will be
252N/Ataken from the SMA agent. Otherwise if 'error' is specified an error will be
252N/Areported and the migration will terminate. If this option is not present then
252N/Athe default behaviour is equivalent to the 'error' flag.
252N/A
252N/A=back
252N/A
252N/A=head1 EXIT STATUS
252N/A
252N/AThe script will exit with 0 if migration was successful, non-zero if a problem
252N/Aoccurred during migration.
252N/A
252N/A=head1 EXAMPLES
252N/A
252N/AFor a simple migration which will fail if there are any potential conflicts:
252N/A
252N/Amasfcnv
252N/A
252N/ATo migrate the MASF configuration such that it will always succeed, MASF
252N/Asettings will override in the event of a conflict with SMA and access will
252N/Astill be provided on the original MASF port:
252N/A
252N/Amasfcnv -is -l agent -p enable -u agent -y agent
252N/A
252N/ATo attempt a dry run and migrate the configuration such that any conflicts
252N/Awill be resolved by retaining existing SMA settings:
252N/A
252N/Amasfcnv -l master -u master -y master
252N/A
252N/A=head1 FILES
252N/A
252N/A=over
252N/A
252N/A=item /etc/sma/snmp/snmpd.conf
252N/A
252N/A=item /var/sma_snmp/snmpd.conf
252N/A
252N/ASMA configuration files
252N/A
252N/A=back
252N/A
252N/A=over
252N/A
252N/A=item /etc/opt/SUNWmasf/conf/snmpd.conf
252N/A
252N/A=item /var/opt/SUNWmasf/snmpd.dat
252N/A
252N/AMASF configuration files
252N/A
252N/A=back
252N/A
252N/A=over
252N/A
252N/A=item /tmp/sma_migration.log
252N/A
252N/Amasfcnv log file
252N/A
252N/A=back
252N/A
252N/A=cut
252N/A
252N/Ause strict;
252N/A
252N/A# Text::ParseWords requires 5.005
252N/Arequire 5.005;
252N/A
252N/Ause Getopt::Long 2.17;
252N/Ause Text::ParseWords;
252N/Ause Net::hostent;
252N/Ause Socket;
252N/Ause Data::Dumper;
252N/Ause File::Copy;
252N/Ause Text::Wrap;
252N/A
252N/A##############################################################################
252N/A# global defaults
252N/A
252N/A# storage for new lines
252N/A%::ADDED_CONFIGS = ('prepend'=>[],
252N/A 'append'=>[]);
252N/A
252N/Ause vars qw ($INTERNET_OID
252N/A $LOG_FILE
252N/A $DATA_DIR
252N/A $FILTER_TYPE_INCLUDED
252N/A $FILTER_TYPE_EXCLUDED
252N/A $ENTITY_MIB_OID
252N/A $SUNPLAT_MIB_OID
252N/A $SNMP_UDP_DOMAIN
252N/A $DEFAULT_ROW_STATUS
252N/A $DEFAULT_STORAGE_TYPE
252N/A $MPMODEL_SNMPV1
252N/A $MPMODEL_SNMPV2C
252N/A $MPMODEL_SNMPV2U
252N/A $MPMODEL_SNMPV3
252N/A $SECURITY_MODEL_ANY
252N/A $SECURITY_MODEL_SNMPV1
252N/A $SECURITY_MODEL_SNMPV2C
252N/A $SECURITY_MODEL_USM
252N/A $SECURITY_LEVEL_NOAUTHNOPRIV
252N/A $SECURITY_LEVEL_AUTHNOPRIV
252N/A $SECURITY_LEVEL_AUTHPRIV
252N/A $NOTIFY_TYPE_TRAP
252N/A $NOTIFY_TYPE_INFORM);
252N/A# location where template files, etc. are stored.
252N/A*LOG_FILE = \"/tmp/sma_migration.log";
252N/A*INTERNET_OID = \".1.3.6.1";
252N/A*DATA_DIR = \"/usr/lib/net_snmp";
252N/A*FILTER_TYPE_INCLUDED = \1;
252N/A*FILTER_TYPE_EXCLUDED = \2;
252N/A*ENTITY_MIB_OID = \".1.3.6.1.2.1.47";
252N/A*SUNPLAT_MIB_OID = \".1.3.6.1.4.1.42.2.70.101";
252N/A*SNMP_UDP_DOMAIN = \".1.3.6.1.6.1.1";
252N/A*DEFAULT_ROW_STATUS = \1;
252N/A*DEFAULT_STORAGE_TYPE = \3;
252N/A*MPMODEL_SNMPV1 = \0;
252N/A*MPMODEL_SNMPV2C = \1;
252N/A*MPMODEL_SNMPV2U = \2;
252N/A*MPMODEL_SNMPV3 = \3;
252N/A*SECURITY_MODEL_ANY = \0;
252N/A*SECURITY_MODEL_SNMPV1 = \1;
252N/A*SECURITY_MODEL_SNMPV2C = \2;
252N/A*SECURITY_MODEL_USM = \3;
252N/A*SECURITY_LEVEL_NOAUTHNOPRIV = \1;
252N/A*SECURITY_LEVEL_AUTHNOPRIV = \2;
252N/A*SECURITY_LEVEL_AUTHPRIV = \3;
252N/A*NOTIFY_TYPE_TRAP = \1;
252N/A*NOTIFY_TYPE_INFORM = \2;
252N/A
252N/A
252N/A##############################################################################
252N/A# misc functions
252N/A
252N/Asub log_message
252N/A{
252N/A my ($msg, $line) = @_;
252N/A if (defined $line && exists $line->{'file'} && exists
252N/A $line->{'lineno'}) {
252N/A $msg = $line->{'file'}.', line '.($line->{'lineno'} + 1).
252N/A ': '.$msg;
252N/A }
252N/A $msg = wrap('', '', $msg);
252N/A if ($::AUTOMATED) {
252N/A open (LOG, ">> $LOG_FILE") ||
252N/A die "Couldn't open log file $LOG_FILE\n";
252N/A print LOG $msg;
252N/A print STDERR $msg;
252N/A close LOG;
252N/A } else {
252N/A print STDERR $msg;
252N/A }
252N/A}
252N/A
252N/Asub get_backup_filename
252N/A{
252N/A my ($fname) = @_;
252N/A if ( -e $fname.'.bak') {
252N/A my ($i) = 0;
252N/A while ( -e $fname.".bak.$i" ) {
252N/A $i++;
252N/A }
252N/A return $fname.".bak.$i";
252N/A }
252N/A return $fname.".bak";
252N/A}
252N/A
252N/Asub backup_files
252N/A{
252N/A log_message "Backing up original files\n";
252N/A my ($f, $newf);
252N/A for $f (@::MASF_CONFIG_FILES, $::MASF_PERSISTENT_FILE, @::SMA_CONFIG_FILES,
252N/A $::SMA_PERSISTENT_FILE) {
252N/A if (! -e $f) {
252N/A next;
252N/A }
252N/A $newf = get_backup_filename($f);
252N/A log_message "Backing up $f to $newf\n";
252N/A if (0 == copy $f, $newf) {
252N/A log_message "Couldn't backup $f - aborting\n";
252N/A exit 1;
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub remove_masf_persistent_file
252N/A{
252N/A if (! -e $::MASF_PERSISTENT_FILE) {
252N/A return;
252N/A }
252N/A log_message "Removing $::MASF_PERSISTENT_FILE\n";
252N/A if (0 == unlink $::MASF_PERSISTENT_FILE) {
252N/A log_message "Couldn't remove MASF persistent storage file\n".
252N/A "$::MASF_PERSISTENT_FILE - Aborting\n";
252N/A exit 1;
252N/A }
252N/A}
252N/A
252N/Asub version
252N/A{
252N/A my ($rev) = '$Revision: 1.3 $';
252N/A $rev=~s/^\$Revision: //;
252N/A $rev=~s/ \$$//;
252N/A print STDERR "$0 $rev\n".
252N/A "Copyright 2003 Sun Microsystems, Inc.\n".
252N/A "All rights reserved.\n".
252N/A "Use is subject to license terms.\n";
252N/A exit 0;
252N/A}
252N/A
252N/Asub stop_sma_running
252N/A{
252N/A `/etc/init.d/init.sma stop`;
252N/A}
252N/A
252N/Asub stop_masf_running
252N/A{
252N/A `/etc/init.d/masfd stop`;
252N/A if (($? >> 8) > 0) {
252N/A log_message "Couldn't stop the MASF agent\n";
252N/A exit 1;
252N/A }
252N/A}
252N/A
252N/Asub set_umask
252N/A{
252N/A # only root should be able to read the config file
252N/A umask 0077;
252N/A}
252N/A
252N/Asub install_new_wrapper_script
252N/A{
252N/A log_message "Installing new MASF startup script\n";
252N/A
252N/A my $pkgInstance='SUNWmasfr';
252N/A my @commands=("/usr/sbin/installf $pkgInstance /etc/init.d/masfd f 744 root sys",
252N/A "/usr/sbin/installf $pkgInstance /etc/rc0.d/K40masfd=/etc/init.d/masfd l",
252N/A "/usr/sbin/installf $pkgInstance /etc/rc1.d/K40masfd=/etc/init.d/masfd l",
252N/A "/usr/sbin/installf $pkgInstance /etc/rc2.d/K40masfd=/etc/init.d/masfd l",
252N/A "/usr/sbin/installf $pkgInstance /etc/rc3.d/S90masfd=/etc/init.d/masfd l",
252N/A "/usr/sbin/installf $pkgInstance /etc/rcS.d/K40masfd=/etc/init.d/masfd l",
252N/A "/usr/sbin/install -f /etc/init.d -m 0744 -u root -g sys $DATA_DIR/masfd",
252N/A "/usr/sbin/installf -f $pkgInstance",
252N/A "/usr/sbin/removef $pkgInstance /etc/rc3.d/S80masfd",
252N/A "/usr/bin/rm /etc/rc3.d/S80masfd",
252N/A "/usr/sbin/removef -f $pkgInstance"
252N/A );
252N/A my $command;
252N/A for $command (@commands) {
252N/A `$command`;
252N/A if ($? >> 8) {
252N/A log_message "A problem occurred whilst installing the MASF startup ".
252N/A "script\n";
252N/A exit 1;
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub install_template_config_file
252N/A{
252N/A if (copy($DATA_DIR.'/snmpd.conf', $::MASF_CONFIG_FILES[0]) == 0) {
252N/A log_message "Couldn't copy template configuration file to ".
252N/A $::MASF_CONFIG_FILES[0]."\n";
252N/A exit 1;
252N/A }
252N/A}
252N/A
252N/Asub are_we_root
252N/A{
252N/A if ($> != 0) {
252N/A log_message "You are not running this as root.\n";
252N/A exit 1;
252N/A }
252N/A}
252N/A
252N/Asub sma_config_sanity_check
252N/A{
252N/A my ($files, $i);
252N/A # check we can read the main config file
252N/A if ( ! -r $::SMA_CONFIG_FILES[0] ) {
252N/A log_message "Couldn't read SMA config file ".
252N/A $::SMA_CONFIG_FILES[0]."\n";
252N/A exit 1;
252N/A }
252N/A for ($i = 0; $i < @::SMA_CONFIG_FILES; $i++) {
252N/A if (! -r $::SMA_CONFIG_FILES[$i]) {
252N/A splice @::SMA_CONFIG_FILES, $i--, 1;
252N/A }
252N/A }
252N/A # check that if the persistent storage file isn't present, that there
252N/A # aren't any stale backups indicating it failed to update it properly
252N/A if ( ! -e $::SMA_PERSISTENT_FILE ) {
252N/A $files = `/bin/ls $::SMA_PERSISTENT_DIR/sma.*.dat 2>/dev/null`;
252N/A if ($files ne '') {
252N/A log_message "Stale SMA agent config files found. The ".
252N/A "SMA agent may not have been shut down cleanly.\n";
252N/A exit 1;
252N/A } else {
252N/A # Assume this is because the agent was never run
252N/A log_message "WARNING: no SMA persistent storage file found\n";
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub masf_config_sanity_check
252N/A{
252N/A my ($files, $i);
252N/A # check we can read the main config file
252N/A if ( ! -r $::MASF_CONFIG_FILES[0] ) {
252N/A log_message "Couldn't read MASF config file ".
252N/A $::MASF_CONFIG_FILES[0]."\n";
252N/A exit 1;
252N/A }
252N/A for ($i = 0; $i < @::MASF_CONFIG_FILES; $i++) {
252N/A if (! -r $::MASF_CONFIG_FILES[$i]) {
252N/A splice @::MASF_CONFIG_FILES, $i--, 1;
252N/A }
252N/A }
252N/A # check that if the persistent storage file isn't present, that there
252N/A # aren't any stale backups indicating it failed to update it properly
252N/A if ( ! -e $::MASF_PERSISTENT_FILE ) {
252N/A $files = `/bin/ls $::MASF_PERSISTENT_DIR/snmpd.*.dat 2>/dev/null`;
252N/A if ($files ne '') {
252N/A log_message "Stale MASF agent config files found. The MASF agent ".
252N/A "may not have been shut down cleanly.\n";
252N/A exit 1;
252N/A } else {
252N/A # Assume this is because the agent was never run
252N/A log_message "WARNING: no MASF persistent storage file found\n";
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub hostnameToUDPDomain
252N/A{
252N/A my ($target) = @_;
252N/A my ($hostname, $port, $hostent);
252N/A my @dotted_decimal;
252N/A ($hostname, $port) = ($target=~/^([^:]+):(\d+)$/);
252N/A if ($port eq "") {
252N/A $port = 162;
252N/A }
252N/A ($hostent) = gethostbyname($hostname);
252N/A @dotted_decimal = unpack ('C4', $hostent->addr_list->[0]);
252N/A return sprintf "0x%02x%02x%02x%02x%04x", @dotted_decimal, $port;
252N/A
252N/A}
252N/A
252N/Asub help
252N/A{
252N/A my ($name) = ($0=~/([^\/]*)$/);
252N/A print STDERR "Usage:
252N/A$name [ -cimnrs ] [ -l agent|master ] [ -p enable|disable|error ]
252N/A [ -t none|add ] [ -u agent|master|error ] [ -y agent|master|error ]
252N/A
252N/A$name [ -V ]
252N/A
252N/A$name [ -? ]
252N/A
252N/A Migrates the configuration of the SNMP Agent for
252N/A Sun Fire Servers to the SMA SNMP Agent
252N/A
252N/AOption Interpretation
252N/A
252N/A-?
252N/A--help
252N/A Display this help message.
252N/A
252N/A-c
252N/A--no-community
252N/A Do not transfer v1/v2c communities
252N/A
252N/A-i
252N/A--ignore-unrecognized-directives
252N/A Continue processing if unrecognised directives are present.
252N/A
252N/A-l agent|master
252N/A--master-trap-target=agent|master
252N/A If 'agent' is specified then the existing SMA trap targets will
252N/A be configured to receive traps that were previously sent to
252N/A destinations for the Sun Fire SNMP agent. If 'master' is
252N/A specified then the targets will be configured to receive Sun
252N/A Fire SNMP traps but existing SNMP target parameters will be used. This
252N/A option may not be used with the \"-t none\" option.
252N/A
252N/A-m
252N/A--no-usmuser
252N/A Do not transfer usm (v3) users
252N/A
252N/A-n
252N/A--dry-run
252N/A Run the migration without modifying any files. If any error
252N/A arises then continue processing. This can be used to determine the
252N/A likely migration issues.
252N/A
252N/A-p enable|disable|error
252N/A--use-agent-port=enable|disable|error
252N/A Indicates whether the port originally used by the Sun Fire SNMP
252N/A agent should be used by the SMA agent after migration (if the
252N/A two agents are using different ports). If 'enable' is specified
252N/A then the port used by the Sun Fire SNMP agent will also be used
252N/A by the SMA agent after migration. If 'disable' is specified then
252N/A the ports used by SMA will not be updated by the migration tool.
252N/A If the 'error' option is specified and the SMA agent is not
252N/A already using the same ports as those used by the original Sun
252N/A Fire SNMP agent then an error will be reported and the migration
252N/A process will be terminated. If no option is specified the default
252N/A behaviour is equivalent to the 'error' flag.
252N/A
252N/A-r
252N/A--no-trap
252N/A Do not transfer trap destinations
252N/A
252N/A-s
252N/A--skip-user
252N/A If a user is found in the MASF configuration file that
252N/A cannot be created in the new configuration due to a change
252N/A in the engine ID, then output a message indicating that
252N/A the user could not be migrated (needs to be manually
252N/A recreated) and continue processing. If this option is not
252N/A present then the migration tool will consider such a
252N/A situation as an error and abort.
252N/A
252N/A-t none|add
252N/A--trap-filter=none|add
252N/A If 'none' is specified then the script will copy trap directives
252N/A directly. The administrator may need to manually update the
252N/A configuration file to ensure traps are only delivered to their
252N/A intended destinations. If 'add' is specifed then trap filters
252N/A will be constructed so that traps originating from the original
252N/A Sun Fire SNMP agent are only delivered to the destinations that
252N/A originally received them. 'add' is the default behaviour.
252N/A
252N/A-u agent|master|error
252N/A--select-user=agent|master|error
252N/A Specifies that if a user with the same name is found in both
252N/A configuration files that the conflict is to be resolved using
252N/A the specified configuration file as input. Selecting a user
252N/A from a particular will also cause the group declaration for
252N/A that user to be taken from the same file. If 'agent' is
252N/A specified then the user will be taken from the configuration
252N/A file for the Sun Fire SNMP Agent. If 'master' is specified then
252N/A the user will be taken from the SMA configuration. Otherwise
252N/A if 'error' is given, the script will terminate. If this option
252N/A is not present then the default behaviour is equivalent to the
252N/A 'error' flag.
252N/A
252N/A-V
252N/A--version
252N/A Display the version of this script.
252N/A
252N/A-y agent|master|error
252N/A--select-community=agent|master|error
252N/A Specifies that if a community and source (hostname, IP addr
252N/A or range of IP addresses) is found to be conflicting in the
252N/A two configurations, which combination should be selected when
252N/A mapping to a security name. If 'agent' is specified then the
252N/A community and source information will be taken from the
252N/A configuration for the Sun Fire SNMP agent. If 'master' is
252N/A specified it will be taken from the SMA agent. Otherwise if
252N/A 'error' is specified an error will be reported and the
252N/A migration will terminate. If this option is not present then
252N/A the default behaviour is equivalent to the 'error' flag.
252N/A
252N/A";
252N/A exit 1;
252N/A}
252N/A
252N/A%::SMA_CONFIGS = ();
252N/A%::MASF_CONFIGS = ();
252N/Asub strip_cr_nl
252N/A{
252N/A # remove \r and \n
252N/A my ($lines, $i);
252N/A for $lines (values %::SMA_CONFIGS) {
252N/A for ($i = 0; $i < @$lines; $i++) {
252N/A chomp $lines->[$i];
252N/A }
252N/A }
252N/A for $lines (values %::MASF_CONFIGS) {
252N/A for ($i = 0; $i < @$lines; $i++) {
252N/A chomp $lines->[$i];
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub read_config_files
252N/A{
252N/A my ($i, @lines);
252N/A for ($i = 0; $i < @::SMA_CONFIG_FILES; $i++) {
252N/A open (FH, '< '.$::SMA_CONFIG_FILES[$i]) || do {
252N/A log_message("Couldn't read config file ".
252N/A $::SMA_CONFIG_FILES[$i]."\n");
252N/A exit 1;
252N/A };
252N/A @lines=<FH>;
252N/A close FH;
252N/A $::SMA_CONFIGS{$::SMA_CONFIG_FILES[$i]} = [@lines];
252N/A }
252N/A if (-e $::SMA_PERSISTENT_FILE) {
252N/A open (FH, '< '.$::SMA_PERSISTENT_FILE) || do {
252N/A log_message("Couldn't read config file ".$::SMA_PERSISTENT_FILE."\n");
252N/A exit 1;
252N/A };
252N/A @lines=<FH>;
252N/A close FH;
252N/A $::SMA_CONFIGS{$::SMA_PERSISTENT_FILE} = [@lines];
252N/A }
252N/A for ($i = 0; $i < @::MASF_CONFIG_FILES; $i++) {
252N/A open (FH, '< '.$::MASF_CONFIG_FILES[$i]) || do {
252N/A log_message("Couldn't read config file ".
252N/A $::MASF_CONFIG_FILES[$i]."\n");
252N/A exit 1;
252N/A };
252N/A @lines=<FH>;
252N/A close FH;
252N/A $::MASF_CONFIGS{$::MASF_CONFIG_FILES[$i]} = [@lines];
252N/A }
252N/A if (-e $::MASF_PERSISTENT_FILE) {
252N/A open (FH, '< '.$::MASF_PERSISTENT_FILE) || do {
252N/A log_message("Couldn't read config file ".
252N/A $::MASF_PERSISTENT_FILE."\n");
252N/A exit 1;
252N/A };
252N/A @lines=<FH>;
252N/A close FH;
252N/A $::MASF_CONFIGS{$::MASF_PERSISTENT_FILE} = [@lines];
252N/A }
252N/A strip_cr_nl();
252N/A}
252N/A
252N/Asub prompt_yes_no
252N/A{
252N/A my ($prompt, $default) = @_;
252N/A my $response = '';
252N/A print STDOUT $prompt," [".$default."]:";
252N/A $response = <STDIN>;
252N/A chomp $response;
252N/A if ($response eq '') {
252N/A $response = $default;
252N/A }
252N/A while (uc($response)!~/^Y|N/) {
252N/A print STDERR "Response must be (y)es or (n)o:";
252N/A $response = <STDIN>;
252N/A chomp $response;
252N/A }
252N/A return $response=~/^[yY]/ ? 'yes' : 'no';
252N/A}
252N/A
252N/Asub prompt
252N/A{
252N/A my ($prompt, $default, $options) = @_;
252N/A my $response = '';
252N/A print STDOUT $prompt," [".$default."]:";
252N/A $response = <STDIN>;
252N/A chomp $response;
252N/A if ($response eq '') {
252N/A $response = $default;
252N/A }
252N/A while (scalar (grep $response eq $_, @$options) != 1) {
252N/A print STDERR "Invalid response:";
252N/A $response = <STDIN>;
252N/A chomp $response;
252N/A }
252N/A return $response;
252N/A}
252N/A
252N/Asub parse_agentaddress
252N/A{
252N/A my ($line)=@_;
252N/A my ($directive, $addresses)=($line=~/^\s*(agentaddress)\s+(.*\S)\s*$/);
252N/A my ($addr, $spec, @addrs, $has_transport_specifier);
252N/A @addrs=split /,/,$addresses;
252N/A foreach $addr (@addrs) {
252N/A $has_transport_specifier=($addr=~/:/);
252N/A if (! $has_transport_specifier) {
252N/A if ($addr=~/^\//) {
252N/A $spec = "unix";
252N/A } else {
252N/A $spec = "udp";
252N/A }
252N/A $addr = $spec.':'.$addr;
252N/A }
252N/A }
252N/A return @addrs;
252N/A}
252N/A
252N/Asub parse_config_line
252N/A{
252N/A my ($line)=@_;
252N/A my @words;
252N/A # strip whitespace
252N/A $line=~s/^\s*//;
252N/A $line=~s/\s*$//;
252N/A # check to see if comment
252N/A if ((substr $line, 0, 1) eq '#') {
252N/A return ('', ());
252N/A }
252N/A @words = &parse_line('\s+', 0, $line);
252N/A if (! defined $words[0]) {
252N/A $words[0] = '';
252N/A }
252N/A return @words;
252N/A}
252N/A
252N/Asub sanity_check_config_files
252N/A{
252N/A my @smaTokens = (
252N/A 'master',
252N/A 'agentxTimeout',
252N/A 'agentxRetries',
252N/A 'agentxPingInterval',
252N/A 'targetParams',
252N/A 'targetAddr',
252N/A 'snmpNotifyFilterProfileTable',
252N/A 'snmpNotifyTable',
252N/A 'snmpNotifyFilterTable'
252N/A );
252N/A my @commonTokens = (
252N/A 'rocommunity',
252N/A 'rwcommunity',
252N/A 'rouser',
252N/A 'rwuser',
252N/A 'agentaddress',
252N/A 'trapsink',
252N/A 'trap2sink',
252N/A 'informsink',
252N/A 'trapcommunity',
252N/A 'com2sec',
252N/A 'group',
252N/A 'access',
252N/A 'view',
252N/A 'engineID',
252N/A 'createUser',
252N/A 'agentgroup',
252N/A 'agentuser',
252N/A 'authtrapenable',
252N/A 'syslocation',
252N/A 'syscontact',
252N/A 'sysname',
252N/A 'sysservices',
252N/A 'engineBoots',
252N/A 'oldEngineID',
252N/A 'usmUser'
252N/A );
252N/A my ($file, $i, $j, $directive, @tokens, $found, $warned, $answer);
252N/A # check sma config files
252N/A $warned = 0;
252N/A for $file (keys %::SMA_CONFIGS) {
252N/A for ($i = 0; $i < @{$::SMA_CONFIGS{$file}}; $i++) {
252N/A $found = 0;
252N/A ($directive, @tokens) = parse_config_line($::SMA_CONFIGS{$file}->[$i]);
252N/A if ($directive eq '') {
252N/A next;
252N/A }
252N/A
252N/A for ($j = 0; $j < @smaTokens; $j++) {
252N/A if ($directive eq $smaTokens[$j]) {
252N/A $found = 1;
252N/A last;
252N/A }
252N/A }
252N/A if ($found) {
252N/A next;
252N/A }
252N/A for ($j = 0; $j < @commonTokens; $j++) {
252N/A if ($directive eq $commonTokens[$j]) {
252N/A $found = 1;
252N/A last;
252N/A }
252N/A }
252N/A if ($found) {
252N/A next;
252N/A }
252N/A # token was not recognised
252N/A log_message("WARNING: Unrecognised token ".$directive.
252N/A " found in file ".$file." at line ".($i + 1)."\n");
252N/A $warned = 1;
252N/A }
252N/A }
252N/A for $file (keys %::MASF_CONFIGS) {
252N/A for ($i = 0; $i < @{$::MASF_CONFIGS{$file}}; $i++) {
252N/A $found = 0;
252N/A ($directive, @tokens) = parse_config_line($::MASF_CONFIGS{$file}->[$i]);
252N/A if ($directive eq '') {
252N/A next;
252N/A }
252N/A
252N/A for ($j = 0; $j < @commonTokens; $j++) {
252N/A if ($directive eq $commonTokens[$j]) {
252N/A $found = 1;
252N/A last;
252N/A }
252N/A }
252N/A if ($found) {
252N/A next;
252N/A }
252N/A # token was not recognised
252N/A log_message("WARNING: Unrecognised token ".$directive.
252N/A " found in file ".$file." at line ".($i + 1)."\n");
252N/A $warned = 1;
252N/A # remove the unrecognised token
252N/A splice @{$::MASF_CONFIGS{$file}}, $i--, 1;
252N/A }
252N/A }
252N/A if ($warned && ! $::IGNORE_UNRECOGNIZED_DIRECTIVES) {
252N/A if ($::AUTOMATED) {
252N/A log_message("Unrecognised tokens found in configuration ".
252N/A "file(s) - aborting\n");
252N/A exit 1;
252N/A } else {
252N/A $answer = prompt_yes_no("Unrecognised tokens were found. Continue?", 'n');
252N/A if ($answer eq 'no') {
252N/A exit 1;
252N/A }
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub print_line
252N/A{
252N/A my ($fh, $line) = @_;
252N/A if (exists $line->{'orig'} && exists $line->{'new'}) {
252N/A if ($line->{'orig'} ne $line->{'new'}) {
252N/A print $fh "# ### CHANGED BY $0 ###\n";
252N/A print $fh '# ',$line->{'orig'},"\n";
252N/A if (exists $line->{'comment'}) {
252N/A print $fh $line->{'comment'},"\n";
252N/A }
252N/A print $fh $line->{'new'},"\n";
252N/A } else {
252N/A print $fh $line->{'orig'},"\n";
252N/A }
252N/A } elsif (exists $line->{'new'}) {
252N/A if (exists $line->{'comment'}) {
252N/A print $fh $line->{'comment'},"\n";
252N/A }
252N/A print $fh $line->{'new'},"\n";
252N/A }
252N/A
252N/A}
252N/A
252N/A@::SMA_PERSISTENT_FILE_TOKENS = (
252N/A 'targetParams', 'targetAddr',
252N/A 'snmpNotifyFilterProfileTable', 'snmpNotifyTable',
252N/A 'snmpNotifyFilterTable', 'engineBoots', 'usmUser', 'oldEngineID',
252N/A 'createUser');
252N/A
252N/A# extract those directives destined for persistent storage
252N/Asub dump_persistent_storage
252N/A{
252N/A my ($file, $persistent_file, $config) = @_;
252N/A #list of tokens which should be in persistent storage
252N/A my ($f, $l, $lines);
252N/A for $f (keys %$config) {
252N/A print $file "# ### IMPORTED FROM $f ###\n\n";
252N/A for $l (@{$config->{$f}}) {
252N/A if (! exists $l->{'new'}) {
252N/A next;
252N/A }
252N/A my ($directive, @toks) = parse_config_line($l->{'new'});
252N/A if ($directive) {
252N/A my (@match) = grep ($_ eq $directive, @::SMA_PERSISTENT_FILE_TOKENS);
252N/A if (@match == 0) {
252N/A # skip this line
252N/A next;
252N/A }
252N/A } elsif ($f ne $persistent_file) {
252N/A # skip all comments/blank lines which are not in the persistent
252N/A # storage file
252N/A next;
252N/A }
252N/A print_line($file, $l);
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub dump_config
252N/A{
252N/A my ($file, $persistent_file, $config) = @_;
252N/A #list of tokens which should be in persistent storage
252N/A my ($f, $l, $lines);
252N/A for $f (keys %$config) {
252N/A print $file "# ### IMPORTED FROM $f ###\n\n";
252N/A for $l (@{$config->{$f}}) {
252N/A if (! exists $l->{'new'}) {
252N/A next;
252N/A }
252N/A my ($directive, @toks) = parse_config_line($l->{'new'});
252N/A if ($directive) {
252N/A my (@match) = grep ($_ eq $directive, @::SMA_PERSISTENT_FILE_TOKENS);
252N/A if (@match > 0) {
252N/A if ($f ne $persistent_file && exists $l->{'orig'}) {
252N/A print $file "# moved to $::SMA_PERSISTENT_FILE >>> ".
252N/A $l->{'orig'}."\n";
252N/A }
252N/A # skip this line
252N/A next;
252N/A }
252N/A } elsif ($f eq $persistent_file) {
252N/A # skip all comments/blank lines which are not in the persistent
252N/A # storage file
252N/A next;
252N/A }
252N/A print_line($file, $l);
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub set_union {
252N/A my ($seta, $setb) = @_;
252N/A my ($i, $j, $found, @out);
252N/A for $i (@$seta, @$setb) {
252N/A $found = 0;
252N/A for $j (@out) {
252N/A if ($j eq $i) {
252N/A $found = 1;
252N/A }
252N/A }
252N/A if (! $found) {
252N/A push @out, $i;
252N/A }
252N/A }
252N/A return @out;
252N/A}
252N/A
252N/Asub in_addr_to_number
252N/A{
252N/A my ($in_addr) = @_;
252N/A my ($i, $N) = (0, 0);
252N/A my (@n) = (unpack 'C4', $in_addr);
252N/A for ($i = 0; $i < @n; $i++) {
252N/A $N = $N << 8;
252N/A $N += $n[$i];
252N/A }
252N/A return $N;
252N/A}
252N/A
252N/Asub splice_line
252N/A{
252N/A my ($config, $line, $length, $offset, @lines) = @_;
252N/A my ($i, $f);
252N/A for $i (@lines) {
252N/A # mark all the lines as changed
252N/A $i->{'changed'} = undef;
252N/A }
252N/A for $f (values %$config) {
252N/A for ($i = 0; $i < @$f; $i++) {
252N/A if ($f->[$i] eq $line) {
252N/A if (@lines) {
252N/A splice @$f, $i + $offset, $length, @lines;
252N/A } else {
252N/A splice @$f, $i + $offset, $length;
252N/A }
252N/A return;
252N/A }
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub prepend_line {
252N/A my ($line) = @_;
252N/A $line->{'changed'} = undef;
252N/A push @{$::ADDED_CONFIGS{'prepend'}}, $line;
252N/A}
252N/A
252N/Asub append_line {
252N/A my ($line) = @_;
252N/A $line->{'changed'} = undef;
252N/A push @{$::ADDED_CONFIGS{'append'}}, $line;
252N/A}
252N/A
252N/Asub replace_line {
252N/A my ($config, $line, @lines) = @_;
252N/A $line->{'meta'} = $lines[0]->{'meta'};
252N/A if (exists $lines[0]->{'new'}) {
252N/A $line->{'new'} = $lines[0]->{'new'};
252N/A } else {
252N/A delete $line->{'new'};
252N/A }
252N/A $lines[0] = $line;
252N/A splice_line($config, $line, 1, 0, @lines);
252N/A}
252N/A
252N/Asub insert_lines {
252N/A my ($config, $line, $after, @lines) = @_;
252N/A my ($offset) = ($after ? 1 : 0);
252N/A splice_line($config, $line, 0, $offset, @lines);
252N/A}
252N/A
252N/Asub get_lines
252N/A{
252N/A my ($directive, $config)=@_;
252N/A my ($line, $lines, @matches);
252N/A for $lines (values %$config) {
252N/A for $line (@$lines) {
252N/A if (exists $line->{'meta'}->{'directive'} &&
252N/A $line->{'meta'}->{'directive'} eq $directive) {
252N/A push @matches, $line;
252N/A }
252N/A }
252N/A }
252N/A return @matches;
252N/A}
252N/A
252N/A##############################################################################
252N/A# Traps
252N/A
252N/Asub remove_trap_destinations
252N/A{
252N/A my (@sinkLines) = (get_lines('trapsink', \%::MASF_CONFIGS),
252N/A get_lines('trap2sink', \%::MASF_CONFIGS),
252N/A get_lines('informsink', \%::MASF_CONFIGS));
252N/A my ($line);
252N/A for $line (@sinkLines) {
252N/A replace_line(\%::MASF_CONFIGS, $line, {'meta'=>{}});
252N/A }
252N/A}
252N/A
252N/Asub get_filters
252N/A{
252N/A my ($keys, $configs)=@_;
252N/A my ($f, $l, @filters);
252N/A for $f (values %$configs) {
252N/A for $l (@$f) {
252N/A if (! exists $l->{'meta'}->{'directive'} ||
252N/A ($l->{'meta'}->{'directive'} ne 'snmpNotifyFilterTable')) {
252N/A next;
252N/A }
252N/A if (exists $keys->{'profileName'} &&
252N/A $l->{'meta'}->{'profileName'} ne $keys->{'profileName'})
252N/A {
252N/A next;
252N/A }
252N/A push @filters, $l;
252N/A }
252N/A }
252N/A return @filters;
252N/A}
252N/A
252N/Asub get_filterProfiles
252N/A{
252N/A my ($keys, $configs)=@_;
252N/A my ($f, $l, @targetAddrs);
252N/A for $f (values %$configs) {
252N/A for $l (@$f) {
252N/A if (! exists $l->{'meta'}->{'directive'} ||
252N/A ($l->{'meta'}->{'directive'} ne 'snmpNotifyFilterProfileTable')) {
252N/A next;
252N/A }
252N/A if (exists $keys->{'paramName'} &&
252N/A $l->{'meta'}->{'paramName'} ne $keys->{'paramName'}) {
252N/A next;
252N/A }
252N/A if (exists $keys->{'profileName'} &&
252N/A $l->{'meta'}->{'profileName'} ne $keys->{'profileName'})
252N/A {
252N/A next;
252N/A }
252N/A push @targetAddrs, $l;
252N/A }
252N/A }
252N/A return @targetAddrs;
252N/A}
252N/A
252N/Asub tag_in_taglist
252N/A{
252N/A my ($tag, $taglist) = @_;
252N/A my (@tags) = split /[ \t\r\n]/,$taglist;
252N/A my ($t);
252N/A for $t (@tags) {
252N/A if ($t eq $tag) {
252N/A return 1;
252N/A }
252N/A }
252N/A return 0;
252N/A}
252N/A
252N/Asub notifyName_exists
252N/A{
252N/A my ($name) = @_;
252N/A my ($file, $line, $meta);
252N/A for $file (values %::MASF_CONFIGS, values %::SMA_CONFIGS) {
252N/A for $line (@$file) {
252N/A $meta=$line->{'meta'};
252N/A if (exists $meta->{'notifyName'} &&
252N/A $meta->{'notifyName'} eq $name) {
252N/A return 1;
252N/A }
252N/A }
252N/A }
252N/A return 0;
252N/A}
252N/A
252N/Asub tag_exists
252N/A{
252N/A my ($tag) = @_;
252N/A my ($file, $line, $meta);
252N/A for $file (values %::MASF_CONFIGS, values %::SMA_CONFIGS) {
252N/A for $line (@$file) {
252N/A $meta = $line->{'meta'};
252N/A if (exists $meta->{'tagList'} &&
252N/A tag_in_taglist ($tag, $meta->{'tagList'})) {
252N/A return 1;
252N/A }
252N/A if (exists $meta->{'notifyTag'} &&
252N/A $tag eq $meta->{'notifyTag'}) {
252N/A return 1;
252N/A }
252N/A }
252N/A }
252N/A return 0;
252N/A}
252N/A
252N/Asub get_new_profileName
252N/A{
252N/A my ($i) = (0);
252N/A my ($try) = ('masfProfile'.$i);
252N/A while (profileName_exists($try)) {
252N/A $i++;
252N/A $try = 'masfProfile'.$i;
252N/A }
252N/A if (length $try > 32) {
252N/A log_message "Unable to generate unique profileName\n";
252N/A exit 1;
252N/A }
252N/A return $try;
252N/A}
252N/A
252N/Asub generate_notify_tags
252N/A{
252N/A my ($prefix) = @_;
252N/A my ($i) = (0);
252N/A while (tag_exists ($prefix.$i) ||
252N/A notifyName_exists ($prefix.$i)) {
252N/A $i++;
252N/A }
252N/A if (length ($prefix.$i) > 255) {
252N/A log_message "Unable to generate valid tag for prefix ".$prefix."\n";
252N/A exit 1;
252N/A }
252N/A return $prefix.$i;
252N/A}
252N/A
252N/Asub get_new_paramName
252N/A{
252N/A my ($i) = (0);
252N/A while (paramName_exists('masfParam'.$i)) {
252N/A $i++;
252N/A }
252N/A if (length 'masfParam'.$i > 32) {
252N/A log_message "Unable to generate unique paramName.\n";
252N/A exit 1;
252N/A }
252N/A return 'masfParam'.$i;
252N/A}
252N/A
252N/Asub get_new_targetName
252N/A{
252N/A my ($host)=@_;
252N/A my ($i)=(0);
252N/A my ($try)=('masfTarget'.$i.$host);
252N/A while (targetName_exists($try) || length $try > 32) {
252N/A if (length $try > 32) {
252N/A chop $host;
252N/A if (length $host == 0) {
252N/A log_message "Unable to generate unique targetName\n";
252N/A exit 1;
252N/A }
252N/A } else {
252N/A $i++;
252N/A }
252N/A $try = 'masfTarget'.$i.$host;
252N/A }
252N/A return $try;
252N/A}
252N/A
252N/Asub paramName_exists
252N/A{
252N/A my ($paramName) = @_;
252N/A my ($keys) = ({'paramName'=>$paramName});
252N/A my (@lines) = (get_targetParams($keys, \%::SMA_CONFIGS),
252N/A get_targetParams($keys, \%::MASF_CONFIGS),
252N/A get_targetAddrs($keys, \%::SMA_CONFIGS),
252N/A get_targetAddrs($keys, \%::MASF_CONFIGS));
252N/A if (@lines) {
252N/A return 1;
252N/A } else {
252N/A return 0;
252N/A }
252N/A}
252N/A
252N/Asub profileName_exists
252N/A{
252N/A my ($name) = @_;
252N/A my ($file, $line, $meta);
252N/A for $file (values %::MASF_CONFIGS, values %::SMA_CONFIGS) {
252N/A for $line (@$file) {
252N/A $meta=$line->{'meta'};
252N/A if (exists $meta->{'profileName'} &&
252N/A $meta->{'profileName'} eq $name) {
252N/A return 1;
252N/A }
252N/A }
252N/A }
252N/A return 0;
252N/A}
252N/A
252N/Asub targetName_exists
252N/A{
252N/A my ($targetName) = @_;
252N/A my ($keys) = ({'targetName'=>$targetName});
252N/A my (@lines) = (get_targetAddrs($keys, \%::SMA_CONFIGS),
252N/A get_targetAddrs($keys, \%::MASF_CONFIGS));
252N/A if (@lines) {
252N/A return 1;
252N/A } else {
252N/A return 0;
252N/A }
252N/A}
252N/A
252N/A# get all target addresses with the specified keys
252N/Asub get_targetAddrs
252N/A{
252N/A my ($keys, $configs)=@_;
252N/A my ($f, $l, @targetAddrs);
252N/A for $f (values %$configs) {
252N/A for $l (@$f) {
252N/A if (! exists $l->{'meta'}->{'directive'} ||
252N/A ($l->{'meta'}->{'directive'} ne 'targetAddr')) {
252N/A next;
252N/A }
252N/A if (exists $keys->{'paramName'} &&
252N/A $l->{'meta'}->{'paramName'} ne $keys->{'paramName'}) {
252N/A next;
252N/A }
252N/A if (exists $keys->{'TDomain'} &&
252N/A $l->{'meta'}->{'TDomain'} ne $keys->{'TDomain'})
252N/A {
252N/A next;
252N/A }
252N/A if (exists $keys->{'TAddress'} &&
252N/A $l->{'meta'}->{'TAddress'} ne $keys->{'TAddress'})
252N/A {
252N/A next;
252N/A }
252N/A if (exists $keys->{'targetName'} &&
252N/A $l->{'meta'}->{'targetName'} ne $keys->{'targetName'})
252N/A {
252N/A next;
252N/A }
252N/A push @targetAddrs, $l;
252N/A }
252N/A }
252N/A return @targetAddrs;
252N/A}
252N/A
252N/A# get all target parameters with the specified keys
252N/Asub get_targetParams
252N/A{
252N/A my ($keys, $configs)=@_;
252N/A my ($f, $l, @targetParams);
252N/A for $f (values %$configs) {
252N/A for $l (@$f) {
252N/A if (! exists $l->{'meta'}->{'directive'} ||
252N/A ($l->{'meta'}->{'directive'} ne 'targetParams')) {
252N/A next;
252N/A }
252N/A if (exists $keys->{'paramName'} &&
252N/A $l->{'meta'}->{'paramName'} ne $keys->{'paramName'}) {
252N/A next;
252N/A }
252N/A if (exists $keys->{'securityModel'} &&
252N/A $l->{'meta'}->{'securityModel'} ne $keys->{'securityModel'})
252N/A {
252N/A next;
252N/A }
252N/A if (exists $keys->{'securityLevel'} &&
252N/A $l->{'meta'}->{'securityLevel'} ne $keys->{'securityLevel'})
252N/A {
252N/A next;
252N/A }
252N/A if (exists $keys->{'securityName'} &&
252N/A $l->{'meta'}->{'securityName'} ne $keys->{'securityName'})
252N/A {
252N/A next;
252N/A }
252N/A push @targetParams, $l;
252N/A }
252N/A }
252N/A return @targetParams;
252N/A}
252N/A
252N/Asub process_trapsink
252N/A{
252N/A my ($sinkLine, $informTag, $trapTag) = @_;
252N/A my ($paramName, @paramLines, $community, @result, $secModel,
252N/A $MPModel, $notifyType, %profiles, $foundParams);
252N/A log_message "Migrating trapsink: ".$sinkLine->{'new'}."\n";
252N/A if ($sinkLine->{'meta'}->{'directive'} eq 'trapsink') {
252N/A $secModel = $SECURITY_MODEL_SNMPV1;
252N/A $MPModel = $MPMODEL_SNMPV1;
252N/A } elsif ($sinkLine->{'meta'}->{'directive'} eq 'trap2sink' ||
252N/A $sinkLine->{'meta'}->{'directive'} eq 'informsink') {
252N/A $secModel = $SECURITY_MODEL_SNMPV2C;
252N/A $MPModel = $MPMODEL_SNMPV2C;
252N/A }
252N/A if ($sinkLine->{'meta'}->{'directive'} eq 'informsink') {
252N/A $notifyType = $NOTIFY_TYPE_INFORM;
252N/A } else {
252N/A $notifyType = $NOTIFY_TYPE_TRAP;
252N/A }
252N/A $community = $sinkLine->{'meta'}->{'community'};
252N/A
252N/A # try to find an existing target param in SMA config but don't bother if we
252N/A # don't care about overlap
252N/A if ($::EXTEND_SMA_FILTERS) {
252N/A @paramLines = (get_targetParams({'securityName'=>$community,
252N/A 'securityModel'=>$SECURITY_MODEL_SNMPV2C}, \%::SMA_CONFIGS),
252N/A get_targetParams({'securityName'=>$community,
252N/A 'securityModel'=>$SECURITY_MODEL_SNMPV1}, \%::SMA_CONFIGS));
252N/A }
252N/A
252N/A my ($smaParamLine, $smaTargetLine);
252N/A my ($targetName, @targetAddrs);
252N/A my ($host) = $sinkLine->{'meta'}->{'host'};
252N/A my ($port) = $sinkLine->{'meta'}->{'port'};
252N/A
252N/A if (@paramLines) {
252N/A my ($paramLine);
252N/A for $paramLine (@paramLines) {
252N/A $paramName = $paramLine->{'meta'}->{'paramName'};
252N/A push @targetAddrs, get_targetAddrs({'TDomain'=>$SNMP_UDP_DOMAIN,
252N/A 'TAddress'=>hostnameToUDPDomain($host.':'.$port),
252N/A 'paramName'=>$paramName}, \%::SMA_CONFIGS)
252N/A }
252N/A
252N/A # try to use an existing targetAddr if it was defined
252N/A if (@targetAddrs > 0) {
252N/A $smaTargetLine = $targetAddrs[0];
252N/A ($smaParamLine) = get_targetParams({'paramName'=>$smaTargetLine->{'meta'}->{'paramName'}}, \%::SMA_CONFIGS);
252N/A $foundParams = 1;
252N/A }
252N/A }
252N/A
252N/A if (! $foundParams || ! $::KEEP_SNMP_TARGET_PARAMS) {
252N/A # we need to generate a new set of params
252N/A $paramName = get_new_paramName();
252N/A push @result, {'meta'=>{'directive'=>'targetParams',
252N/A 'paramName'=>$paramName,
252N/A 'MPModel'=>$MPModel,
252N/A 'securityModel'=>$secModel,
252N/A 'securityName'=>$community,
252N/A 'securityLevel'=>$SECURITY_LEVEL_AUTHNOPRIV,
252N/A 'storageType'=>$DEFAULT_STORAGE_TYPE,
252N/A 'rowStatus'=>$DEFAULT_ROW_STATUS}
252N/A };
252N/A }
252N/A
252N/A my (@profiles, $profileName);
252N/A
252N/A if (! $foundParams) {
252N/A # no equivalent SMA target found - only MASF traps to be delivered
252N/A # generate our own targetAddr
252N/A my ($i) = (0);
252N/A $targetName = get_new_targetName($host);
252N/A push @result, {'meta'=>{'directive'=>'targetAddr',
252N/A 'targetName'=>$targetName,
252N/A 'TDomain'=>$SNMP_UDP_DOMAIN,
252N/A 'TAddress'=>hostnameToUDPDomain($host.':'.$port),
252N/A 'timeout'=>1500,
252N/A 'retryCount'=>3,
252N/A 'tagList'=>$notifyType == $NOTIFY_TYPE_INFORM ? $informTag :
252N/A $trapTag,
252N/A 'paramName'=>$paramName,
252N/A 'storageType'=>$DEFAULT_STORAGE_TYPE,
252N/A 'rowStatus'=>$DEFAULT_ROW_STATUS}};
252N/A # need to add a filter profile
252N/A $profileName = get_new_profileName();
252N/A } elsif (! $::KEEP_SNMP_TARGET_PARAMS) {
252N/A # we need to change the targetAddr to refer to the new set of params
252N/A $targetName = $smaTargetLine->{'meta'}->{'targetName'};
252N/A $smaTargetLine->{'meta'}->{'paramName'} = $paramName;
252N/A $smaTargetLine->{'meta'}->{'tagList'} =
252N/A ($notifyType == $NOTIFY_TYPE_INFORM ? $informTag : $trapTag);
252N/A replace_line(\%::SMA_CONFIGS, $smaTargetLine, $smaTargetLine);
252N/A
252N/A # set our params to use the new set of filter profiles
252N/A @profiles = get_filterProfiles(
252N/A {'paramName'=>$smaParamLine->{'meta'}->{'paramName'}},
252N/A \%::SMA_CONFIGS);
252N/A if (@profiles > 0) {
252N/A $profileName = $profiles[0]->{'meta'}->{'profileName'};
252N/A } else {
252N/A # no filter profiles defined
252N/A return @result;
252N/A }
252N/A } else {
252N/A # don't change existing target specification
252N/A # SMA profiles already have MASF added.
252N/A return @result;
252N/A }
252N/A
252N/A push @result, {'meta'=>{'directive'=>'snmpNotifyFilterProfileTable',
252N/A 'paramName'=>$paramName,
252N/A 'profileName'=>$profileName,
252N/A 'storageType'=>$DEFAULT_STORAGE_TYPE,
252N/A 'rowStatus'=>$DEFAULT_ROW_STATUS}
252N/A };
252N/A
252N/A if ($foundParams) {
252N/A return @result;
252N/A }
252N/A
252N/A # add some filters
252N/A push @result,
252N/A {'comment'=>'# Include ENTITY-MIB and SUN-PLATFORM-MIB in profile',
252N/A 'meta'=>{'directive'=>'snmpNotifyFilterTable',
252N/A 'profileName'=>$profileName,
252N/A 'subtree'=>$ENTITY_MIB_OID,
252N/A 'mask'=>'',
252N/A 'filterType'=>$FILTER_TYPE_INCLUDED,
252N/A 'storageType'=>$DEFAULT_STORAGE_TYPE,
252N/A 'rowStatus'=>$DEFAULT_ROW_STATUS
252N/A }},
252N/A {'meta'=>{'directive'=>'snmpNotifyFilterTable',
252N/A 'profileName'=>$profileName,
252N/A 'subtree'=>$SUNPLAT_MIB_OID,
252N/A 'mask'=>'',
252N/A 'filterType'=>$FILTER_TYPE_INCLUDED,
252N/A 'storageType'=>$DEFAULT_STORAGE_TYPE,
252N/A 'rowStatus'=>$DEFAULT_ROW_STATUS
252N/A }};
252N/A return @result;
252N/A}
252N/A
252N/Asub process_trapsinks
252N/A{
252N/A # grab all the trapsink, trap2sink and informsink lines in MASF
252N/A my (@sinkLines) = (get_lines('trapsink', \%::MASF_CONFIGS),
252N/A get_lines('trap2sink', \%::MASF_CONFIGS),
252N/A get_lines('informsink', \%::MASF_CONFIGS));
252N/A my ($sinkLine, $paramName, @paramLines, $community, @result, $secModel,
252N/A $MPModel, $notifyType, $informTag, $trapTag, %profiles, $foundParams);
252N/A %profiles=();
252N/A foreach $sinkLine (@sinkLines) {
252N/A $paramName = undef;
252N/A @result = ();
252N/A $foundParams = 0;
252N/A log_message "Processing trapsink: ".$sinkLine->{'new'}."\n";
252N/A if (!defined $informTag) {
252N/A $informTag = generate_notify_tags('masfInformTag');
252N/A log_message "Using tag ".$informTag." for informs\n";
252N/A $trapTag = generate_notify_tags('masfTrapTag');
252N/A log_message "Using tag ".$trapTag." for traps\n";
252N/A push @result, {'meta'=>{'directive'=>'snmpNotifyTable',
252N/A 'notifyName'=>$informTag,
252N/A 'notifyTag'=>$informTag,
252N/A 'notifyType'=>$NOTIFY_TYPE_INFORM,
252N/A 'storageType'=>$DEFAULT_STORAGE_TYPE,
252N/A 'rowStatus'=>$DEFAULT_ROW_STATUS
252N/A }},
252N/A {'meta'=>{'directive'=>'snmpNotifyTable',
252N/A 'notifyName'=>$trapTag,
252N/A 'notifyTag'=>$trapTag,
252N/A 'notifyType'=>$NOTIFY_TYPE_TRAP,
252N/A 'storageType'=>$DEFAULT_STORAGE_TYPE,
252N/A 'rowStatus'=>$DEFAULT_ROW_STATUS
252N/A }};
252N/A }
252N/A push @result, process_trapsink($sinkLine, $informTag, $trapTag);
252N/A replace_line(\%::MASF_CONFIGS, $sinkLine, @result);
252N/A }
252N/A}
252N/A
252N/Asub extend_sma_trap_filters
252N/A{
252N/A my (@lines, $line);
252N/A @lines = get_lines('snmpNotifyFilterTable', \%::SMA_CONFIGS);
252N/A my (%hash);
252N/A foreach $line (@lines) {
252N/A if (!exists $hash{$line->{'meta'}->{'profileName'}}) {
252N/A log_message "Adding ENTITY-MIB and SUN-PLATFORM-MIB traps to ".
252N/A "trap filter profile ".$line->{'meta'}->{'profileName'}."\n";
252N/A $hash{$line->{'meta'}->{'profileName'}}=undef;
252N/A insert_lines(\%::SMA_CONFIGS, $line, 0,
252N/A {'comment'=>'# Include ENTITY-MIB and SUN-PLATFORM-MIB in profile',
252N/A 'meta'=>{'directive'=>'snmpNotifyFilterTable',
252N/A 'profileName'=>$line->{'meta'}->{'profileName'},
252N/A 'subtree'=>$ENTITY_MIB_OID,
252N/A 'mask'=>'',
252N/A 'filterType'=>$FILTER_TYPE_INCLUDED,
252N/A 'storageType'=>$DEFAULT_STORAGE_TYPE,
252N/A 'rowStatus'=>$DEFAULT_ROW_STATUS}},
252N/A {'meta'=>{'directive'=>'snmpNotifyFilterTable',
252N/A 'profileName'=>$line->{'meta'}->{'profileName'},
252N/A 'subtree'=>$SUNPLAT_MIB_OID,
252N/A 'mask'=>'',
252N/A 'filterType'=>$FILTER_TYPE_INCLUDED,
252N/A 'storageType'=>$DEFAULT_STORAGE_TYPE,
252N/A 'rowStatus'=>$DEFAULT_ROW_STATUS}});
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub process_trapcommunity
252N/A{
252N/A my ($configs)=@_;
252N/A my ($i, $file, $trapcommunity, $meta);
252N/A $trapcommunity = 'public';
252N/A foreach $file (values %$configs) {
252N/A for ($i = 0; $i < @$file; $i++) {
252N/A $meta = $file->[$i]->{'meta'};
252N/A if (! exists $file->[$i]->{'meta'}->{'directive'}) {
252N/A next;
252N/A }
252N/A if ($meta->{'directive'} eq 'trapcommunity') {
252N/A $trapcommunity = $meta->{'community'};
252N/A replace_line($configs, $file->[$i], {'meta'=>{}});
252N/A next;
252N/A }
252N/A if ($meta->{'directive'} eq 'trapsink' ||
252N/A $meta->{'directive'} eq 'trap2sink' ||
252N/A $meta->{'directive'} eq 'informsink') {
252N/A if (! exists $meta->{'community'}) {
252N/A $meta->{'community'} = $trapcommunity;
252N/A replace_line($configs, $file->[$i], $file->[$i]);
252N/A }
252N/A if (! exists $meta->{'port'}) {
252N/A $meta->{'port'} = 162;
252N/A replace_line($configs, $file->[$i], $file->[$i]);
252N/A }
252N/A }
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub check_duplicate_trap_destinations
252N/A{
252N/A my (@smaTraps) = (get_lines('informsink', \%::SMA_CONFIGS),
252N/A get_lines('trapsink', \%::SMA_CONFIGS),
252N/A get_lines('trap2sink', \%::SMA_CONFIGS));
252N/A my (@masfTraps) = (get_lines('informsink', \%::MASF_CONFIGS),
252N/A get_lines('trapsink', \%::MASF_CONFIGS),
252N/A get_lines('trap2sink', \%::MASF_CONFIGS));
252N/A my ($trap, @matches, $match);
252N/A for $trap (@masfTraps) {
252N/A @matches = grep (
252N/A ($_->{'meta'}->{'community'} eq $trap->{'meta'}->{'community'} &&
252N/A $_->{'meta'}->{'host'} eq $trap->{'meta'}->{'host'} &&
252N/A $_->{'meta'}->{'port'} eq $trap->{'meta'}->{'port'}), @smaTraps);
252N/A if (@matches) {
252N/A # remove this duplicate
252N/A log_message "Removing duplicate ".$trap->{'meta'}->{'directive'}." directive\n", $trap;
252N/A replace_line(\%::MASF_CONFIGS, $trap, {'meta'=>{}});
252N/A }
252N/A }
252N/A}
252N/A
252N/A##############################################################################
252N/A# Access control, groups and users
252N/A
252N/A$::SEEDED = 0;
252N/A
252N/Asub remove_v3_users
252N/A{
252N/A my (@users) = get_securityNames({'securityModel'=>'usm'}, \%::MASF_CONFIGS);
252N/A my ($user, @groups, $group);
252N/A for $user (@users) {
252N/A replace_line(\%::MASF_CONFIGS, $user, {'meta'=>{}});
252N/A @groups = get_groups($user->{'meta'}, \%::MASF_CONFIGS);
252N/A for $group (@groups) {
252N/A replace_line(\%::MASF_CONFIGS, $group, {'meta'=>{}});
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub remove_v1v2c_users
252N/A{
252N/A my (@users) = get_securityNames({'securityModel'=>'v1'}, \%::MASF_CONFIGS);
252N/A my ($user, @groups, $group);
252N/A for $user (@users) {
252N/A replace_line(\%::MASF_CONFIGS, $user, {'meta'=>{}});
252N/A @groups = get_groups($user->{'meta'}, \%::MASF_CONFIGS);
252N/A for $group (@groups) {
252N/A replace_line(\%::MASF_CONFIGS, $group, {'meta'=>{}});
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub generate_password
252N/A{
252N/A my ($i, $r, $pwd);
252N/A if (! $::SEEDED) {
252N/A srand;
252N/A $::SEEDED=1;
252N/A }
252N/A
252N/A for ($i = 0; $i < 8; $i++) {
252N/A do {
252N/A $r = chr (int (rand 127));
252N/A } while ($r!~/^[a-zA-Z0-9]$/);
252N/A $pwd.=$r;
252N/A }
252N/A return $pwd;
252N/A}
252N/A
252N/A# check to see whether MASF UsmUser directives can be transferred without
252N/A# alteration, if not then convert to a template createUser statement
252N/Asub process_engineIDs
252N/A{
252N/A log_message "\n";
252N/A log_message "Checking to see if USM users defined in usmUser directives can be migrated without modification:\n";
252N/A my ($lines, $line, $can_migrate);
252N/A $can_migrate = 1;
252N/A # check that no v3 users have been specified in SMA
252N/A my (@v3_sma_users) = (get_securityNames({'securityModel'=>'usm'}, \%::SMA_CONFIGS));
252N/A if (@v3_sma_users > 0) {
252N/A log_message "V3 users were specified in SMA config - cannot migrate without modification.\n";
252N/A $can_migrate = 0;
252N/A }
252N/A # If the engineID was specified in MASF then we cannot migrate. Remove it
252N/A # from the migrated configuration
252N/A for $line (get_lines('engineID', \%::MASF_CONFIGS)) {
252N/A $can_migrate = 0;
252N/A log_message "engineID specified in configuration file - cannot migrate without modification.\n", $line;
252N/A replace_line(\%::MASF_CONFIGS, $line, {'meta'=>{}});
252N/A }
252N/A # check that engineID isn't specified anywhere in SMA config
252N/A for $line (get_lines('engineID', \%::SMA_CONFIGS)) {
252N/A log_message "engineID specified in configuration file - cannot migrate without modification.\n", $line;
252N/A $can_migrate = 0;
252N/A }
252N/A
252N/A if (! $can_migrate) {
252N/A for $line (get_lines('usmUser', \%::MASF_CONFIGS)) {
252N/A if (! $::IGNORE_ENGINEID) {
252N/A log_message "User with securityName ".
252N/A $line->{'meta'}->{'securityName'}." cannot be migrated ".
252N/A "because the engineID has changed - aborting.\n", $line;
252N/A exit 1;
252N/A }
252N/A log_message "\n";
252N/A log_message "***************************************************************************\n";
252N/A log_message 'User with securityName '.
252N/A $line->{'meta'}->{'securityName'}." has had their password reset.\n";
252N/A log_message "You will need to edit the configuration file after ".
252N/A "this script has finished\n".
252N/A "in order to enable their account\n";
252N/A log_message "***************************************************************************\n";
252N/A replace_line(\%::MASF_CONFIGS, $line,
252N/A {'comment'=>'# XXX Change the password if necessary',
252N/A 'meta'=>{'directive'=>'createUser',
252N/A 'securityModel'=>'usm',
252N/A 'securityName'=>$line->{'meta'}->{'securityName'},
252N/A 'authPassword'=>generate_password(),
252N/A 'authProtocol'=>'MD5'}});
252N/A }
252N/A # if we can't migrate the engineID, then remove any oldEngineID
252N/A # statements and engineBoots statements
252N/A for $line (get_lines('oldEngineID', \%::MASF_CONFIGS),
252N/A get_lines('engineBoots', \%::MASF_CONFIGS)) {
252N/A replace_line(\%::MASF_CONFIGS, $line, {'meta'=>{}});
252N/A }
252N/A return;
252N/A } else {
252N/A log_message "OK to migrate usm users\n";
252N/A }
252N/A
252N/A # check to see if oldEngineID or engineBoots is defined in SMA config - if
252N/A # so then squash it in favour of new one from MASF
252N/A for $line (get_lines('oldEngineID', \%::SMA_CONFIGS),
252N/A get_lines('engineBoots', \%::SMA_CONFIGS)) {
252N/A replace_line(\%::SMA_CONFIGS, $line, {'meta'=>{}});
252N/A }
252N/A}
252N/A
252N/A# ensure that if a createUser and usmUser directive is present for the same
252N/A# securityName then the createUser directive takes precedence
252N/Asub check_usm_securityNames
252N/A{
252N/A my (@masfUserLines)=(get_securityNames({'securityModel'=>'usm'},
252N/A \%::MASF_CONFIGS));
252N/A my (@smaUserLines)=(get_securityNames({'securityModel'=>'usm'},
252N/A \%::SMA_CONFIGS));
252N/A my ($usmUser, $user, $config);
252N/A for $config (\%::MASF_CONFIGS, \%::SMA_CONFIGS) {
252N/A my (@userLines) = (get_securityNames({'securityModel'=>'usm'},
252N/A $config));
252N/A my (@createUsers) = (grep 'createUser' eq $_->{'meta'}->{'directive'}, @userLines);
252N/A for $user (@createUsers) {
252N/A my (@usmUsers) = (grep (('usmUser' eq $_->{'meta'}->{'directive'}
252N/A && $user->{'meta'}->{'securityName'} eq
252N/A $_->{'meta'}->{'securityName'}), @userLines));
252N/A for $usmUser (@usmUsers) {
252N/A replace_line($config, $usmUser, {'meta'=>{}});
252N/A }
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub choose_group_membership
252N/A{
252N/A my ($smaSecurityName, $masfSecurityName) = @_;
252N/A # interactive mode
252N/A convert_metadata();
252N/A log_message "\nThis user is defined in SMA with the following configuration:\n";
252N/A # get the config:
252N/A my ($o, $n) = get_old_new_config($smaSecurityName,
252N/A \%::SMA_CONFIGS);
252N/A
252N/A log_message "Original configuration:\n".join ("\n",@$o);
252N/A log_message "\n\nProposed configuration 1:\n".join ("\n",@$n);
252N/A ($o, $n) = get_old_new_config($masfSecurityName, \%::MASF_CONFIGS);
252N/A log_message "\n\nIt conflicts with the following MASF configuration:\nOriginal configuration:\n".join ("\n", @$o);
252N/A log_message "\n\nProposed configuration 2:\n".join ("\n",@$n)."\n";
252N/A my ($response) = (prompt ("Please choose one of the".
252N/A " proposed configurations", 1, [1,2]));
252N/A if ($response == 1) {
252N/A remove_com2sec_user ({'securityName'=>$masfSecurityName}, \%::MASF_CONFIGS);
252N/A } else {
252N/A remove_com2sec_user ({'securityName'=>$smaSecurityName}, \%::SMA_CONFIGS);
252N/A }
252N/A}
252N/A
252N/Asub process_usm_securityNames
252N/A{
252N/A my ($file, $line, $fileb, $lineb, $snameLine, $sname, $conflicted);
252N/A for $snameLine (get_securityNames({'securityModel'=>'usm'}, \%::MASF_CONFIGS)) {
252N/A $sname = $snameLine->{'meta'}->{'securityName'};
252N/A $conflicted = undef;
252N/A for $file (values %::SMA_CONFIGS) {
252N/A for $line (@$file) {
252N/A if (exists $line->{'meta'}->{'securityName'} &&
252N/A $line->{'meta'}->{'securityName'} eq $sname) {
252N/A $conflicted=$line;
252N/A last;
252N/A }
252N/A }
252N/A }
252N/A if (defined $conflicted) {
252N/A # there is a clash
252N/A log_message "MASF securityName ".$sname." conflicts with one already defined in SMA\n", $snameLine;
252N/A if ($::KEEP_SMA_USM_USERS) {
252N/A remove_com2sec_user($snameLine->{'meta'}, \%::MASF_CONFIGS);
252N/A } elsif ($::KEEP_MASF_USM_USERS) {
252N/A remove_com2sec_user($conflicted->{'meta'}, \%::SMA_CONFIGS);
252N/A } elsif ($::AUTOMATED) {
252N/A log_message "Conflicting securityNames found - aborting. Please resolve these conflicts\n".
252N/A "manually.\n";
252N/A exit 1;
252N/A } else {
252N/A choose_group_membership($conflicted->{'meta'}->{'securityName'}, $sname);
252N/A }
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub remove_com2sec_user
252N/A{
252N/A my ($keys, $config)=@_;
252N/A my ($securityName)=($keys->{'securityName'});
252N/A my ($f, $l);
252N/A for $l (get_securityNames($keys, $config)) {
252N/A replace_line ($config, $l, {'meta'=>{}});
252N/A }
252N/A for $f (values %$config) {
252N/A for $l (@$f) {
252N/A if (exists $l->{'meta'}->{'directive'} &&
252N/A $l->{'meta'}->{'directive'} eq 'group' &&
252N/A $l->{'meta'}->{'securityName'} eq $securityName) {
252N/A replace_line($config, $l, {'meta'=>{}});
252N/A }
252N/A }
252N/A }
252N/A}
252N/A
252N/A# get all lines which define a security name i.e. com2sec, createUser or
252N/A# usmUser, according to specified keys
252N/Asub get_securityNames
252N/A{
252N/A my ($keys, $configs)=@_;
252N/A my ($f, $l, @securityNames);
252N/A for $f (values %$configs) {
252N/A for $l (@$f) {
252N/A if (! exists $l->{'meta'}->{'directive'} ||
252N/A ($l->{'meta'}->{'directive'} ne 'createUser' &&
252N/A $l->{'meta'}->{'directive'} ne 'usmUser' &&
252N/A $l->{'meta'}->{'directive'} ne 'com2sec')) {
252N/A next;
252N/A }
252N/A if (exists $keys->{'securityName'} &&
252N/A $l->{'meta'}->{'securityName'} ne $keys->{'securityName'}) {
252N/A next;
252N/A }
252N/A if (exists $keys->{'securityModel'}) {
252N/A my ($sm) = ('usm');
252N/A if ($keys->{'securityModel'} eq 'v2c' ||
252N/A $keys->{'securityModel'} eq 'v1') {
252N/A $sm = 'v1';
252N/A }
252N/A if (($sm eq 'v1' &&
252N/A $l->{'meta'}->{'directive'} ne 'com2sec') ||
252N/A ($sm eq 'usm' &&
252N/A ($l->{'meta'}->{'directive'} ne 'createUser' &&
252N/A $l->{'meta'}->{'directive'} ne 'usmUser'))) {
252N/A next;
252N/A }
252N/A }
252N/A push @securityNames, $l;
252N/A }
252N/A }
252N/A return @securityNames;
252N/A}
252N/A
252N/Asub get_groups
252N/A{
252N/A my ($keys, $configs)=@_;
252N/A my ($f, $l, @groups);
252N/A for $f (values %$configs) {
252N/A for $l (@$f) {
252N/A if (! exists $l->{'meta'}->{'directive'} ||
252N/A $l->{'meta'}->{'directive'} ne 'group') {
252N/A next;
252N/A }
252N/A if (exists $keys->{'securityName'} &&
252N/A $l->{'meta'}->{'securityName'} ne $keys->{'securityName'}) {
252N/A next;
252N/A }
252N/A if (exists $keys->{'securityModel'} &&
252N/A $l->{'meta'}->{'securityModel'} ne $keys->{'securityModel'}) {
252N/A next;
252N/A }
252N/A if (exists $keys->{'groupName'} &&
252N/A $l->{'meta'}->{'groupName'} ne $keys->{'groupName'}) {
252N/A next;
252N/A }
252N/A push @groups, $l
252N/A }
252N/A }
252N/A return @groups;
252N/A}
252N/A
252N/Asub get_access {
252N/A my ($keys, $configs)=@_;
252N/A my ($f, $l, @access);
252N/A for $f (values %$configs) {
252N/A for $l (@$f) {
252N/A if (! exists $l->{'meta'}->{'directive'} ||
252N/A $l->{'meta'}->{'directive'} ne 'access') {
252N/A next;
252N/A }
252N/A if (exists $keys->{'groupName'} &&
252N/A $l->{'meta'}->{'groupName'} ne $keys->{'groupName'}) {
252N/A next;
252N/A }
252N/A if (exists $keys->{'viewName'} &&
252N/A ($l->{'meta'}->{'readView'} ne $keys->{'viewName'} &&
252N/A $l->{'meta'}->{'writeView'} ne $keys->{'viewName'} &&
252N/A $l->{'meta'}->{'notifyView'} ne $keys->{'viewName'})) {
252N/A next;
252N/A }
252N/A push @access, $l
252N/A }
252N/A }
252N/A return @access;
252N/A}
252N/A
252N/Asub get_views {
252N/A my ($keys, $configs)=@_;
252N/A my ($f, $l, @views);
252N/A if (exists $keys->{'viewName'} &&
252N/A $keys->{'viewName'} eq '') {
252N/A return ();
252N/A }
252N/A for $f (values %$configs) {
252N/A for $l (@$f) {
252N/A if (! exists $l->{'meta'}->{'directive'} ||
252N/A $l->{'meta'}->{'directive'} ne 'view') {
252N/A next;
252N/A }
252N/A if (exists $keys->{'viewName'} &&
252N/A $l->{'meta'}->{'viewName'} ne $keys->{'viewName'}) {
252N/A next;
252N/A }
252N/A push @views, $l
252N/A }
252N/A }
252N/A return @views;
252N/A}
252N/A
252N/Asub get_old_new_config
252N/A{
252N/A my ($securityName, $configs) = @_;
252N/A my ($line, @secNames, @groups, $group, $access, @accesses, @views, @old, @new);
252N/A my (@a, $keys);
252N/A $keys = {'securityName'=>$securityName};
252N/A @secNames = get_securityNames($keys, $configs);
252N/A @groups = get_groups ({'securityName'=>$securityName}, $configs);
252N/A # get other members of this group
252N/A if (@groups > 0) {
252N/A @groups = set_union([get_groups({'groupName'=>$groups[0]->{'meta'}->{'groupName'}}, $configs)], \@groups);
252N/A }
252N/A for $group (@groups) {
252N/A (@accesses) = (set_union(\@accesses, [get_access($group->{'meta'}, $configs)]));
252N/A }
252N/A for $access (@accesses) {
252N/A $keys = {'viewName'=>$access->{'meta'}->{'readView'}};
252N/A (@views) = (set_union(\@views, [get_views($keys, $configs)]));
252N/A $keys->{'viewName'}=$access->{'meta'}->{'writeView'};
252N/A (@views) = (set_union(\@views, [get_views($keys, $configs)]));
252N/A $keys->{'viewName'}=$access->{'meta'}->{'notifyView'};
252N/A (@views) = (set_union(\@views, [get_views($keys, $configs)]));
252N/A }
252N/A for $line (@secNames, @groups, @accesses, @views) {
252N/A if (exists $line->{'orig'}) {
252N/A push @old, $line->{'orig'};
252N/A }
252N/A if (exists $line->{'new'}) {
252N/A push @new, $line->{'new'};
252N/A }
252N/A }
252N/A return [@old], [@new];
252N/A}
252N/A
252N/Asub parse_source
252N/A{
252N/A my ($line) = @_;
252N/A my ($source) = $line->{'meta'}->{'source'};
252N/A my ($hostIP, $mask, $ipSegment);
252N/A # was it 'default'
252N/A if ($source eq 'default' || $source eq '0.0.0.0') {
252N/A return (inet_aton('0.0.0.0'), inet_aton('0.0.0.0'));
252N/A }
252N/A # try to resolve as a plain IP address or a hostname
252N/A $ipSegment=$source;
252N/A ($ipSegment, $mask) = split /\//, $source;
252N/A # try to resolve hostname as an IP address
252N/A my ($hostent) = gethostbyname($ipSegment);
252N/A if (defined $hostent) {
252N/A if ($hostent->addrtype ne AF_INET) {
252N/A log_message "Unsupported address family in source $source\n", $line;
252N/A exit 1;
252N/A }
252N/A my (@hostIPs) = @{$hostent->addr_list};
252N/A log_message "resolved $source to ".inet_ntoa($hostIPs[0])."\n", $line;
252N/A $hostIP = $hostIPs[0];
252N/A } else {
252N/A log_message "Couldn't resolve $ipSegment as a hostname or IP address\n", $line;
252N/A exit 1;
252N/A }
252N/A # try to resolve as subnet/mask
252N/A if (defined $mask && $mask ne '') {
252N/A my $netmask;
252N/A $netmask = inet_aton($mask);
252N/A if (! defined $netmask) {
252N/A
252N/A # try to interpret as number between 0 and 32
252N/A my ($bit) = (0x80000000);
252N/A $netmask = 0;
252N/A if ($mask < 0 || $mask > 32) {
252N/A log_message "$source did not contain a valid netmask.\n", $line;
252N/A exit 1;
252N/A }
252N/A while ($mask > 0) {
252N/A $netmask |= $bit;
252N/A $bit = $bit >> 1;
252N/A }
252N/A }
252N/A my ($N, $H) = (in_addr_to_number ($netmask), in_addr_to_number
252N/A ($hostIP));
252N/A if ($H & ~$N) {
252N/A log_message("source/mask mismatch - ".inet_ntoa($hostIP).'/'.inet_ntoa($netmask)."\n", $line);
252N/A exit 1;
252N/A }
252N/A return ($hostIP, $netmask);
252N/A } else {
252N/A # no netmask specified - exact match
252N/A return ($hostIP, inet_aton('255.255.255.255'));
252N/A }
252N/A}
252N/A
252N/Asub source_overlap
252N/A{
252N/A my ($linea, $lineb) = @_;
252N/A my ($ipa, $maska) = parse_source($linea);
252N/A my ($ipb, $maskb) = parse_source($lineb);
252N/A my $mask_overlap;
252N/A $ipa = in_addr_to_number($ipa);
252N/A $ipb = in_addr_to_number($ipb);
252N/A $mask_overlap = in_addr_to_number($maska) & in_addr_to_number($maskb);
252N/A my $complement = 0xffffffff & (~$mask_overlap);
252N/A if (($ipa & $mask_overlap | $complement) == ($ipb & $mask_overlap | $complement)) {
252N/A return 1;
252N/A }
252N/A return 0;
252N/A}
252N/A
252N/Asub community_conflicts
252N/A{
252N/A my ($linea)=@_;
252N/A my ($community, $source) = ($linea->{'meta'}->{'community'}, $linea->{'meta'}->{'source'});
252N/A my ($lines, $line);
252N/A for $lines (values %::SMA_CONFIGS) {
252N/A for $line (@$lines) {
252N/A if (! exists $line->{'meta'}->{'community'} ||
252N/A $line->{'meta'}->{'community'} ne $community) {
252N/A next;
252N/A }
252N/A if (! exists $line->{'meta'}->{'source'}) {
252N/A next;
252N/A }
252N/A if (source_overlap ($line, $linea)) {
252N/A return ($line);
252N/A }
252N/A }
252N/A }
252N/A return undef;
252N/A}
252N/A
252N/Asub process_com2sec
252N/A{
252N/A my ($lines, $line);
252N/A my $conflict;
252N/A for $lines (values %::MASF_CONFIGS) {
252N/A for $line (@$lines) {
252N/A if (! exists $line->{'meta'}->{'directive'} ||
252N/A $line->{'meta'}->{'directive'} ne 'com2sec') {
252N/A next;
252N/A }
252N/A
252N/A $conflict = community_conflicts($line);
252N/A if (defined $conflict) {
252N/A log_message "MASF source ".$line->{'meta'}->{'source'}.
252N/A " conflicts with SMA source ".$conflict->{'meta'}->{'source'}.
252N/A " defined for community ".$line->{'meta'}->{'community'}."\n", $line;
252N/A if ($::KEEP_SMA_GROUPS) {
252N/A # remove user from MASF config
252N/A remove_com2sec_user ($line->{'meta'}, \%::MASF_CONFIGS);
252N/A } elsif ($::KEEP_MASF_GROUPS) {
252N/A # remove user from SMA config
252N/A remove_com2sec_user ($line->{'meta'}, \%::SMA_CONFIGS);
252N/A } elsif ($::AUTOMATED) {
252N/A # didn't define what to do so stop!
252N/A log_message "Conflicting source/communities found - ".
252N/A "aborting. Please resolve these conflicts manually.\n";
252N/A exit 1;
252N/A } else {
252N/A choose_group_membership($conflict->{'meta'}->{'securityName'}, $line->{'meta'}->{'securityName'});
252N/A }
252N/A }
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub uniquify_viewNames
252N/A{
252N/A my ($prefix) = @_;
252N/A my %mappings=();
252N/A my ($lines, $line, $securityName, $i, @keys, $key, $from);
252N/A @keys = ('viewName', 'readView', 'writeView', 'notifyView');
252N/A for $lines (values %::MASF_CONFIGS) {
252N/A foreach $line (@$lines) {
252N/A for $key (@keys) {
252N/A if (exists $line->{'meta'}->{$key} &&
252N/A $line->{'meta'}->{$key} ne '') {
252N/A $from = $line->{'meta'}->{$key};
252N/A } else {
252N/A next;
252N/A }
252N/A
252N/A # is there already a mapping for this securityName ?
252N/A if (exists $mappings{$from}) {
252N/A $line->{'meta'}->{$key} = $mappings{$from};
252N/A replace_line(\%::MASF_CONFIGS, $line, $line);
252N/A next;
252N/A }
252N/A
252N/A # generate a new securityName
252N/A $i = 0;
252N/A while (viewName_exists($prefix.$i.$from))
252N/A {
252N/A $i++;
252N/A }
252N/A if (length $prefix.$i.$from > 32) {
252N/A log_message ("Couldn't render viewName $from unique\n", $line);
252N/A exit 1;
252N/A }
252N/A $mappings{$from}=$prefix.$i.$from;
252N/A $line->{'meta'}->{$key} = $prefix.$i.$from;
252N/A replace_line(\%::MASF_CONFIGS, $line, $line);
252N/A }
252N/A }
252N/A }
252N/A # remove redundant view names
252N/A my (@viewLines, @accessLines, $view, $config);
252N/A for $config (\%::MASF_CONFIGS, \%::SMA_CONFIGS) {
252N/A @viewLines = get_views({}, $config);
252N/A for $view (@viewLines) {
252N/A @accessLines = (get_access($view->{'meta'}, \%::MASF_CONFIGS), get_access($view->{'meta'}, \%::SMA_CONFIGS));
252N/A if (@accessLines == 0) {
252N/A replace_line($config, $view, {'meta'=>{}});
252N/A }
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub uniquify_groupNames
252N/A{
252N/A my ($prefix) = @_;
252N/A my %mappings=();
252N/A my ($lines, $line, $securityName, $i, $from);
252N/A for $lines (values %::MASF_CONFIGS) {
252N/A foreach $line (@$lines) {
252N/A if (exists $line->{'meta'}->{'groupName'}) {
252N/A $from = $line->{'meta'}->{'groupName'};
252N/A } else {
252N/A next;
252N/A }
252N/A
252N/A # is there already a mapping for this securityName ?
252N/A if (exists $mappings{$from}) {
252N/A $line->{'meta'}->{'groupName'} = $mappings{$from};
252N/A replace_line(\%::MASF_CONFIGS, $line, $line);
252N/A next;
252N/A }
252N/A
252N/A # generate a new securityName
252N/A $i = 0;
252N/A while (groupName_exists($prefix.$i.$from))
252N/A {
252N/A $i++;
252N/A }
252N/A if (length $prefix.$i.$from > 32) {
252N/A log_message ("Couldn't render groupName $from unique\n", $line);
252N/A exit 1;
252N/A }
252N/A $mappings{$from}=$prefix.$i.$from;
252N/A $line->{'meta'}->{'groupName'} = $prefix.$i.$from;
252N/A replace_line(\%::MASF_CONFIGS, $line, $line);
252N/A }
252N/A }
252N/A}
252N/A
252N/A# remove group directives referring to undefined users
252N/Asub clean_group_membership
252N/A{
252N/A my ($config);
252N/A for $config (\%::MASF_CONFIGS, \%::SMA_CONFIGS) {
252N/A my (@groups) = get_lines('group', $config);
252N/A my ($group);
252N/A for $group (@groups) {
252N/A my (@securityNames) = get_securityNames($group->{'meta'}, $config);
252N/A if (@securityNames == 0) {
252N/A # no securityName was defined for this directive - remove the
252N/A # directive
252N/A log_message "Removing undefined user ".
252N/A $group->{'meta'}->{'securityName'}." from group ".
252N/A $group->{'meta'}->{'groupName'}."\n", $group;
252N/A replace_line($config, $group, {'meta'=>{}});
252N/A }
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub uniquify_securityNames
252N/A{
252N/A my ($prefix) = @_;
252N/A my ($to);
252N/A my ($lines, $line, $securityName, $i, $from, $fromLine);
252N/A for $fromLine (get_securityNames({'securityModel'=>'v1'},
252N/A \%::MASF_CONFIGS)) {
252N/A # generate a new securityName
252N/A $from = $fromLine->{'meta'}->{'securityName'};
252N/A $to = get_new_securityName($prefix.$from);
252N/A for $lines (values %::MASF_CONFIGS) {
252N/A foreach $line (@$lines) {
252N/A if (! exists $line->{'meta'}->{'securityName'} ||
252N/A $line->{'meta'}->{'securityName'} ne $from) {
252N/A next;
252N/A }
252N/A
252N/A $line->{'meta'}->{'securityName'} = $to;
252N/A replace_line(\%::MASF_CONFIGS, $line, $line);
252N/A }
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub check_tokens
252N/A{
252N/A my ($line, $minTokens, $maxTokens, @tokens) = @_;
252N/A my ($directive) = $line->{'meta'}->{'directive'};
252N/A if (@tokens < $minTokens || @tokens > $maxTokens) {
252N/A log_message "Invalid number of parameters for $directive directive ".
252N/A "- Aborting\n", $line;
252N/A exit 1;
252N/A }
252N/A}
252N/A
252N/A# convert simple array of lines into hash containing data which is what we
252N/A# subsequently modify
252N/Asub add_metadata
252N/A{
252N/A my ($lines, $file, $line, $i, $s, $directive, @tokens);
252N/A my ($key, $j);
252N/A for $key (keys %::SMA_CONFIGS) {
252N/A for ($i = 0; $i < @{$::SMA_CONFIGS{$key}}; $i++) {
252N/A $line = $::SMA_CONFIGS{$key}->[$i];
252N/A $::SMA_CONFIGS{$key}->[$i] = {'orig'=>$line,
252N/A 'new'=>$line,
252N/A # NB the 'meta' hash doesn't contain metadata, only real data...
252N/A 'meta'=>{},
252N/A 'lineno'=>$i,
252N/A 'file'=>$key};
252N/A }
252N/A }
252N/A for $key (keys %::MASF_CONFIGS) {
252N/A for ($i = 0; $i < @{$::MASF_CONFIGS{$key}}; $i++) {
252N/A $line = $::MASF_CONFIGS{$key}->[$i];
252N/A $::MASF_CONFIGS{$key}->[$i] = {'orig'=>$line,
252N/A 'new'=>$line,
252N/A 'meta'=>{},
252N/A 'lineno'=>$i,
252N/A 'file'=>$key};
252N/A }
252N/A }
252N/A for $lines (values %::SMA_CONFIGS, values %::MASF_CONFIGS) {
252N/A for $line (@$lines) {
252N/A ($directive, @tokens) = parse_config_line($line->{'new'});
252N/A if ($directive ne '') {
252N/A $line->{'meta'}->{'directive'} = $directive;
252N/A }
252N/A if ($directive eq 'com2sec') {
252N/A check_tokens($line, 3, 3, @tokens);
252N/A $line->{'meta'}->{'securityName'} = $tokens[0];
252N/A $line->{'meta'}->{'source'} = $tokens[1];
252N/A $line->{'meta'}->{'community'} = $tokens[2];
252N/A } elsif ($directive eq 'group') {
252N/A check_tokens($line, 3, 3, @tokens);
252N/A $line->{'meta'}->{'groupName'} = $tokens[0];
252N/A $line->{'meta'}->{'securityModel'} = $tokens[1];
252N/A $line->{'meta'}->{'securityName'} = $tokens[2];
252N/A } elsif ($directive eq 'rouser' || $directive eq 'rwuser') {
252N/A check_tokens($line, 1, 3, @tokens);
252N/A $line->{'meta'}->{'securityName'} = $tokens[0];
252N/A if (defined $tokens[1]) {
252N/A $line->{'meta'}->{'securityLevel'} = $tokens[1];
252N/A }
252N/A if (defined $tokens[2]) {
252N/A $line->{'meta'}->{'oid'} = $tokens[2];
252N/A }
252N/A } elsif ($directive eq 'createUser') {
252N/A check_tokens($line, 3, 5, @tokens);
252N/A $line->{'meta'}->{'securityName'} = $tokens[0];
252N/A $line->{'meta'}->{'authProtocol'} = $tokens[1];
252N/A $line->{'meta'}->{'authPassword'} = $tokens[2];
252N/A $line->{'meta'}->{'securityModel'} = 'usm';
252N/A if (defined $tokens[3]) {
252N/A $line->{'meta'}->{'privProtocol'} = $tokens[3];
252N/A }
252N/A if (defined $tokens[4]) {
252N/A $line->{'meta'}->{'privPassword'} = $tokens[4];
252N/A }
252N/A } elsif ($directive eq 'usmUser') {
252N/A check_tokens($line, 11, 11, @tokens);
252N/A $line->{'meta'}->{'securityName'} = securityName_from_usmUser($directive, @tokens);
252N/A $line->{'meta'}->{'securityModel'} = 'usm';
252N/A } elsif ($directive eq 'access') {
252N/A check_tokens($line, 8, 8, @tokens);
252N/A $line->{'meta'}->{'groupName'} = $tokens[0];
252N/A $line->{'meta'}->{'contextPrefix'} = $tokens[1];
252N/A $line->{'meta'}->{'securityModel'} = $tokens[2];
252N/A $line->{'meta'}->{'securityLevel'} = $tokens[3];
252N/A $line->{'meta'}->{'contextMatch'} = $tokens[4];
252N/A $line->{'meta'}->{'readView'} = $tokens[5];
252N/A $line->{'meta'}->{'writeView'} = $tokens[6];
252N/A $line->{'meta'}->{'notifyView'} = $tokens[7];
252N/A } elsif ($directive eq 'view') {
252N/A check_tokens($line, 3, 4, @tokens);
252N/A $line->{'meta'}->{'viewName'} = $tokens[0];
252N/A $line->{'meta'}->{'viewType'} = $tokens[1];
252N/A $line->{'meta'}->{'oid'} = $tokens[2];
252N/A if (defined $tokens[3]) {
252N/A $line->{'meta'}->{'mask'} = $tokens[3];
252N/A }
252N/A } elsif ($directive eq 'rocommunity' || $directive eq 'rwcommunity') {
252N/A check_tokens($line, 1, 3, @tokens);
252N/A $line->{'meta'}->{'community'} = $tokens[0];
252N/A if (defined $tokens[1]) {
252N/A $line->{'meta'}->{'source'} = $tokens[1];
252N/A } else {
252N/A $line->{'meta'}->{'source'} = "0.0.0.0/0.0.0.0";
252N/A }
252N/A if (defined $tokens[2]) {
252N/A $line->{'meta'}->{'oid'} = $tokens[2];
252N/A }
252N/A } elsif ($directive eq 'trapcommunity') {
252N/A check_tokens($line, 1, 1, @tokens);
252N/A $line->{'meta'}->{'community'} = $tokens[0];
252N/A } elsif ($directive eq 'trapsink' ||
252N/A $directive eq 'trap2sink' ||
252N/A $directive eq 'informsink') {
252N/A check_tokens($line, 1, 3, @tokens);
252N/A $line->{'meta'}->{'host'} = $tokens[0];
252N/A if (defined $tokens[1]) {
252N/A $line->{'meta'}->{'community'} = $tokens[1];
252N/A }
252N/A if (defined $tokens[2]) {
252N/A $line->{'meta'}->{'port'} = $tokens[2];
252N/A }
252N/A } elsif ($directive eq 'snmpNotifyFilterTable') {
252N/A check_tokens($line, 6, 6, @tokens);
252N/A $line->{'meta'}->{'profileName'} = $tokens[0];
252N/A $line->{'meta'}->{'subtree'} = $tokens[1];
252N/A $line->{'meta'}->{'mask'} = $tokens[2];
252N/A $line->{'meta'}->{'filterType'} = $tokens[3];
252N/A $line->{'meta'}->{'storageType'} = $tokens[4];
252N/A $line->{'meta'}->{'rowStatus'} = $tokens[5];
252N/A } elsif ($directive eq 'targetParams') {
252N/A check_tokens($line, 7, 7, @tokens);
252N/A $line->{'meta'}->{'paramName'} = $tokens[0];
252N/A $line->{'meta'}->{'MPModel'} = $tokens[1];
252N/A $line->{'meta'}->{'securityModel'} = $tokens[2];
252N/A $line->{'meta'}->{'securityName'} = $tokens[3];
252N/A $line->{'meta'}->{'securityLevel'} = $tokens[4];
252N/A $line->{'meta'}->{'storageType'} = $tokens[5];
252N/A $line->{'meta'}->{'rowStatus'} = $tokens[6];
252N/A } elsif ($directive eq 'targetAddr') {
252N/A check_tokens($line, 9, 9, @tokens);
252N/A $line->{'meta'}->{'targetName'} = $tokens[0];
252N/A $line->{'meta'}->{'TDomain'} = $tokens[1];
252N/A $line->{'meta'}->{'TAddress'} = $tokens[2];
252N/A $line->{'meta'}->{'timeout'} = $tokens[3];
252N/A $line->{'meta'}->{'retryCount'} = $tokens[4];
252N/A $line->{'meta'}->{'tagList'} = $tokens[5];
252N/A $line->{'meta'}->{'paramName'} = $tokens[6];
252N/A $line->{'meta'}->{'storageType'} = $tokens[7];
252N/A $line->{'meta'}->{'rowStatus'} = $tokens[8];
252N/A } elsif ($directive eq 'snmpNotifyTable') {
252N/A check_tokens($line, 5, 5, @tokens);
252N/A $line->{'meta'}->{'notifyName'} = $tokens[0];
252N/A $line->{'meta'}->{'notifyTag'} = $tokens[1];
252N/A $line->{'meta'}->{'notifyType'} = $tokens[2];
252N/A $line->{'meta'}->{'storageType'} = $tokens[3];
252N/A $line->{'meta'}->{'rowStatus'} = $tokens[4];
252N/A } elsif ($directive eq 'snmpNotifyFilterProfileTable') {
252N/A check_tokens($line, 4, 4, @tokens);
252N/A $line->{'meta'}->{'paramName'} = $tokens[0];
252N/A $line->{'meta'}->{'profileName'} = $tokens[1];
252N/A $line->{'meta'}->{'storageType'} = $tokens[2];
252N/A $line->{'meta'}->{'rowStatus'} = $tokens[3];
252N/A } elsif ($directive eq 'master') {
252N/A check_tokens($line, 1, 1, @tokens);
252N/A $line->{'meta'}->{'masterMode'} = $tokens[0];
252N/A } elsif ($directive eq 'agentxTimeout') {
252N/A check_tokens($line, 1, 1, @tokens);
252N/A $line->{'meta'}->{'agentxTimeout'} = $tokens[0];
252N/A } elsif ($directive eq 'agentxRetries') {
252N/A check_tokens($line, 1, 1, @tokens);
252N/A $line->{'meta'}->{'agentxRetries'} = $tokens[0];
252N/A }
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub convert_metadata
252N/A{
252N/A my ($line, $file, $meta, $directive);
252N/A my %mps = ($MPMODEL_SNMPV1=>'v1',
252N/A $MPMODEL_SNMPV2C=>'v2c',
252N/A $MPMODEL_SNMPV2U=>'v2u',
252N/A $MPMODEL_SNMPV3=>'v3');
252N/A my %sms = ($SECURITY_MODEL_ANY=>'any',
252N/A $SECURITY_MODEL_SNMPV1=>'v1',
252N/A $SECURITY_MODEL_SNMPV2C=>'v2c',
252N/A $SECURITY_MODEL_USM=>'usm');
252N/A my %sls = ($SECURITY_LEVEL_NOAUTHNOPRIV=>'noAuthNoPriv',
252N/A $SECURITY_LEVEL_AUTHNOPRIV=>'authNoPriv',
252N/A $SECURITY_LEVEL_AUTHPRIV=>'authPriv');
252N/A my %nts = ($NOTIFY_TYPE_TRAP=>'trap',
252N/A $NOTIFY_TYPE_INFORM=>'inform');
252N/A for $file (values %::ADDED_CONFIGS, values %::MASF_CONFIGS, values
252N/A %::SMA_CONFIGS) {
252N/A for $line (@$file) {
252N/A $meta = $line->{'meta'};
252N/A if (exists $meta->{'directive'} &&
252N/A exists $line->{'changed'}) {
252N/A delete $line->{'changed'};
252N/A $directive = $meta->{'directive'};
252N/A if ($directive eq 'com2sec') {
252N/A # don't quote securityName or community
252N/A $line->{'new'} = "com2sec ".$meta->{'securityName'}.
252N/A ' '.$meta->{'source'}.' '.$meta->{'community'};
252N/A } elsif ($directive eq 'group') {
252N/A # don't quote groupName
252N/A $line->{'new'} = 'group '.$meta->{'groupName'}.
252N/A ' '.$meta->{'securityModel'}.' '.
252N/A # don't quote securityName
252N/A $meta->{'securityName'}.'';
252N/A } elsif ($directive eq 'access') {
252N/A my ($readView, $writeView, $notifyView) =
252N/A map { $_ eq '' ? 'none' : $_ }
252N/A ($meta->{'readView'}, $meta->{'writeView'},
252N/A $meta->{'notifyView'});
252N/A # don't quote groupName, or viewNames
252N/A $line->{'new'} = 'access '.$meta->{'groupName'}.
252N/A ' "'.$meta->{'contextPrefix'}.'" '.
252N/A $meta->{'securityModel'}.' '.$meta->{'securityLevel'}.
252N/A ' '.$meta->{'contextMatch'}.' '.$readView.
252N/A ' '.$writeView.' '.$notifyView;
252N/A } elsif ($directive eq 'view') {
252N/A # don't quote viewName
252N/A $line->{'new'} = 'view '.$meta->{'viewName'}.' '.
252N/A $meta->{'viewType'}.' '.$meta->{'oid'};
252N/A if (exists $meta->{'mask'}) {
252N/A $line->{'new'}.=' '.$meta->{'mask'};
252N/A }
252N/A } elsif ($directive eq 'createUser') {
252N/A $line->{'new'} = 'createUser "'.$meta->{'securityName'}.
252N/A '" '.$meta->{'authProtocol'}.' "'.$meta->{'authPassword'}.
252N/A '"';
252N/A if (exists $meta->{'privProtocol'}) {
252N/A $line->{'new'}.=' '.$meta->{'privProtocol'};
252N/A }
252N/A if (exists $meta->{'privPassword'}) {
252N/A $line->{'new'}.=' "'.$meta->{'privPassword'}.'" ';
252N/A }
252N/A } elsif ($directive eq 'trap2sink' ||
252N/A $directive eq 'trapsink' ||
252N/A $directive eq 'informsink') {
252N/A $line->{'new'} = $directive.' '.$meta->{'host'};
252N/A if (exists $meta->{'community'}) {
252N/A # don't quote community
252N/A $line->{'new'}.=' '.$meta->{'community'}.'';
252N/A }
252N/A if (exists $meta->{'port'}) {
252N/A $line->{'new'}.=' '.$meta->{'port'};
252N/A }
252N/A } elsif ($directive eq 'snmpNotifyFilterTable') {
252N/A $line->{'new'} = 'snmpNotifyFilterTable "'.
252N/A $meta->{'profileName'}.'" '.$meta->{'subtree'}.' "'.
252N/A $meta->{'mask'}.'" '.$meta->{'filterType'}.' '.
252N/A $meta->{'storageType'}.' '.$meta->{'rowStatus'};
252N/A } elsif ($directive eq 'targetParams') {
252N/A $line->{'comment'} = '# targetParams '.$meta->{'paramName'}.
252N/A ' '.$mps{$meta->{'MPModel'}}.' '.
252N/A $sms{$meta->{'securityModel'}}.' '.$meta->{'securityName'}.
252N/A ' '.$sls{$meta->{'securityLevel'}};
252N/A $line->{'new'} = 'targetParams "'.$meta->{'paramName'}.'" '.
252N/A $meta->{'MPModel'}.' '.$meta->{'securityModel'}.' "'.
252N/A $meta->{'securityName'}.'" '.$meta->{'securityLevel'}.' '.
252N/A $meta->{'storageType'}.' '.$meta->{'rowStatus'};
252N/A } elsif ($directive eq 'targetAddr') {
252N/A $line->{'new'} = 'targetAddr "'.$meta->{'targetName'}.
252N/A '" '.$meta->{'TDomain'}.' '.$meta->{'TAddress'}.
252N/A ' '.$meta->{'timeout'}.' '.$meta->{'retryCount'}.
252N/A ' "'.$meta->{'tagList'}.'" "'.$meta->{'paramName'}.
252N/A '" '.$meta->{'storageType'}.' '.$meta->{'rowStatus'};
252N/A } elsif ($directive eq 'snmpNotifyTable') {
252N/A $line->{'comment'} = '# snmpNotifyTable '.$meta->{'notifyName'}.
252N/A ' '.$meta->{'notifyTag'}.' '.$nts{$meta->{'notifyType'}};
252N/A $line->{'new'} = 'snmpNotifyTable "'.$meta->{'notifyName'}.
252N/A '" "'.$meta->{'notifyTag'}.'" '.$meta->{'notifyType'}.
252N/A ' '.$meta->{'storageType'}.' '.$meta->{'rowStatus'};
252N/A } elsif ($directive eq 'snmpNotifyFilterProfileTable') {
252N/A $line->{'new'} = 'snmpNotifyFilterProfileTable "'.
252N/A $meta->{'paramName'}.'" "'.$meta->{'profileName'}.
252N/A '" '.$meta->{'storageType'}.' '.$meta->{'rowStatus'};
252N/A } elsif ($directive eq 'master') {
252N/A $line->{'new'} = 'master '.$meta->{'masterMode'};
252N/A } elsif ($directive eq 'agentxTimeout') {
252N/A $line->{'new'} = 'agentxTimeout '.$meta->{'agentxTimeout'};
252N/A } elsif ($directive eq 'agentxRetries') {
252N/A $line->{'new'} = 'agentxRetries '.$meta->{'agentxRetries'};
252N/A }
252N/A }
252N/A }
252N/A }
252N/A}
252N/A
252N/A
252N/A# convert all rwuser directives to rouser
252N/Asub convert_rwusers
252N/A{
252N/A my ($line, $file);
252N/A my ($directive, @tokens);
252N/A for $line (get_lines('rwuser', \%::MASF_CONFIGS)) {
252N/A $line->{'meta'}->{'directive'} = 'rouser';
252N/A replace_line(\%::MASF_CONFIGS, $line, $line);
252N/A }
252N/A}
252N/A
252N/A# convert all rwcommunity directives to rocommunity
252N/Asub convert_rwcommunities
252N/A{
252N/A my ($line);
252N/A for $line (get_lines('rwcommunity', \%::MASF_CONFIGS)) {
252N/A $line->{'meta'}->{'directive'} = 'rocommunity';
252N/A replace_line(\%::MASF_CONFIGS, $line, $line);
252N/A }
252N/A}
252N/A
252N/Asub securityName_from_usmUser
252N/A{
252N/A my ($directive, @tokens) = @_;
252N/A my ($string);
252N/A $tokens[3]=~s/^0x//;
252N/A $string = pack 'H*', $tokens[3];
252N/A return unpack 'Z*', $string;
252N/A}
252N/A
252N/Asub viewName_exists
252N/A{
252N/A my ($viewName) = @_;
252N/A my ($file, $line, $meta);
252N/A for $file (values %::MASF_CONFIGS, values %::SMA_CONFIGS) {
252N/A for $line (@$file) {
252N/A $meta=$line->{'meta'};
252N/A if ((exists $meta->{'readView'} &&
252N/A $meta->{'readView'} eq $viewName) ||
252N/A (exists $meta->{'writeView'} &&
252N/A $meta->{'writeView'} eq $viewName) ||
252N/A (exists $meta->{'notifyView'} &&
252N/A $meta->{'notifyView'} eq $viewName) ||
252N/A (exists $meta->{'viewName'} &&
252N/A $meta->{'viewName'} eq $viewName)) {
252N/A return 1;
252N/A }
252N/A }
252N/A }
252N/A return 0;
252N/A}
252N/A
252N/Asub get_new_viewName
252N/A{
252N/A my ($prefix)=@_;
252N/A my ($viewName, $i);
252N/A $i = 0;
252N/A
252N/A do {
252N/A $viewName = $prefix.$i;
252N/A if (length $viewName > 32) {
252N/A log_message("viewName $viewName was longer than 32 characters\n");
252N/A exit 1;
252N/A }
252N/A $i++;
252N/A } while (viewName_exists($viewName));
252N/A return $viewName;
252N/A}
252N/A
252N/Asub groupName_exists
252N/A{
252N/A my ($groupName) = @_;
252N/A my ($file, $line, $meta);
252N/A for $file (values %::MASF_CONFIGS, values %::SMA_CONFIGS) {
252N/A for $line (@$file) {
252N/A $meta=$line->{'meta'};
252N/A if (exists $meta->{'groupName'} &&
252N/A $meta->{'groupName'} eq $groupName) {
252N/A return 1;
252N/A }
252N/A }
252N/A }
252N/A return 0;
252N/A}
252N/A
252N/Asub get_new_groupName
252N/A{
252N/A my ($prefix)=@_;
252N/A my ($groupName, $i);
252N/A $i = 0;
252N/A
252N/A do {
252N/A $groupName = $prefix.$i;
252N/A if (length $groupName > 32) {
252N/A log_message("groupName $groupName was longer than 32 characters\n");
252N/A exit 1;
252N/A }
252N/A $i++;
252N/A } while (groupName_exists($groupName));
252N/A return $groupName;
252N/A}
252N/A
252N/Asub securityName_exists
252N/A{
252N/A my ($securityName) = @_;
252N/A my ($file, $line, $meta);
252N/A for $file (values %::MASF_CONFIGS, values %::SMA_CONFIGS) {
252N/A for $line (@$file) {
252N/A $meta=$line->{'meta'};
252N/A
252N/A if (exists $meta->{'securityName'} &&
252N/A $meta->{'securityName'} eq $securityName) {
252N/A return 1;
252N/A }
252N/A }
252N/A }
252N/A return 0;
252N/A}
252N/A
252N/Asub get_new_securityName
252N/A{
252N/A my ($prefix)=@_;
252N/A my ($securityName, $i);
252N/A $i = 0;
252N/A
252N/A do {
252N/A $securityName = $prefix.$i;
252N/A # check to see if length is more than 32 characters permitted
252N/A # by VACM
252N/A if (length $securityName > 32) {
252N/A log_message("securityName $securityName was longer".
252N/A " than 32 characters\n");
252N/A exit 1;
252N/A }
252N/A
252N/A $i++;
252N/A } while (securityName_exists($securityName));
252N/A return $securityName;
252N/A}
252N/A
252N/Asub expand_rouser
252N/A{
252N/A my ($line, $default_oids) = @_;
252N/A my ($securityName, $groupName, $viewName, $secLevel, $oid);
252N/A my (@output, $readView, $writeView, $i);
252N/A @output = ($line);
252N/A $securityName = $line->{'meta'}->{'securityName'};
252N/A if (! defined $line->{'meta'}->{'securityLevel'}) {
252N/A $secLevel = "auth";
252N/A } else {
252N/A $secLevel = $line->{'meta'}->{'securityLevel'};
252N/A }
252N/A if (! defined $line->{'meta'}->{'oid'}) {
252N/A $oid = '';
252N/A } else {
252N/A $oid = $line->{'meta'}->{'oid'};
252N/A }
252N/A
252N/A $groupName = get_new_groupName("Group");
252N/A $viewName = get_new_viewName("View");
252N/A
252N/A if ($line->{'meta'}->{'directive'} eq 'rouser') {
252N/A $readView = $viewName;
252N/A $writeView = '';
252N/A } else {
252N/A $readView = $viewName;
252N/A $writeView = $viewName;
252N/A }
252N/A
252N/A $output[0]->{'meta'} = {'directive'=>'group',
252N/A 'groupName'=>$groupName,
252N/A 'securityModel'=>'usm',
252N/A 'securityName'=>$securityName};
252N/A push @output, {'meta'=>{'directive'=>'access',
252N/A 'groupName'=>$groupName,
252N/A 'contextPrefix'=>'',
252N/A 'securityModel'=>'usm',
252N/A 'securityLevel'=>$secLevel,
252N/A 'contextMatch'=>'exact',
252N/A 'readView'=>$readView,
252N/A 'writeView'=>$writeView,
252N/A 'notifyView'=>''}
252N/A };
252N/A if ($oid ne '') {
252N/A push @output, {'meta'=>{'directive'=>'view',
252N/A 'viewName'=>$viewName,
252N/A 'viewType'=>'included',
252N/A 'oid'=>$oid}};
252N/A } else {
252N/A for ($i = 0; $i < @$default_oids; $i++) {
252N/A push @output,{'meta'=>{'directive'=>'view',
252N/A 'viewName'=>$viewName,
252N/A 'viewType'=>'included',
252N/A 'oid'=>$default_oids->[$i]}};
252N/A }
252N/A }
252N/A return @output;
252N/A}
252N/A
252N/Asub expand_rocommunity
252N/A{
252N/A my ($line, $default_oids) = @_;
252N/A my ($securityName, $groupName, $viewName, $community, $source, $oid);
252N/A my (@output, $readView, $writeView, $i);
252N/A @output = ($line);
252N/A $community = $line->{'meta'}->{'community'};
252N/A $source = $line->{'meta'}->{'source'};
252N/A if (defined $line->{'meta'}->{'oid'}) {
252N/A $oid = $line->{'meta'}->{'oid'};
252N/A } else {
252N/A $oid = '';
252N/A }
252N/A
252N/A $securityName = get_new_securityName("User");
252N/A $groupName = get_new_groupName("Group");
252N/A $viewName = get_new_viewName("View");
252N/A
252N/A if ($line->{'meta'}->{'directive'} eq 'rocommunity') {
252N/A $readView = $viewName;
252N/A $writeView = '';
252N/A } else {
252N/A $readView = $viewName;
252N/A $writeView = $viewName;
252N/A }
252N/A
252N/A $output[0]->{'meta'} = {'directive'=>"com2sec",
252N/A 'securityName'=>$securityName,
252N/A 'source'=>$source,
252N/A 'community'=>$community
252N/A };
252N/A push @output, {'meta'=>{'directive'=>'group',
252N/A 'groupName'=>$groupName,
252N/A 'securityModel'=>'v1',
252N/A 'securityName'=>$securityName}
252N/A },
252N/A {'meta'=>{'directive'=>'group',
252N/A 'groupName'=>$groupName,
252N/A 'securityModel'=>'v2c',
252N/A 'securityName'=>$securityName}
252N/A },
252N/A {'meta'=>{'directive'=>'access',
252N/A 'groupName'=>$groupName,
252N/A 'contextPrefix'=>'',
252N/A 'securityModel'=>'v1',
252N/A 'securityLevel'=>'noauth',
252N/A 'contextMatch'=>'exact',
252N/A 'readView'=>$readView,
252N/A 'writeView'=>$writeView,
252N/A 'notifyView'=>''}
252N/A },
252N/A {'meta'=>{'directive'=>'access',
252N/A 'groupName'=>$groupName,
252N/A 'contextPrefix'=>'',
252N/A 'securityModel'=>'v2c',
252N/A 'securityLevel'=>'noauth',
252N/A 'contextMatch'=>'exact',
252N/A 'readView'=>$readView,
252N/A 'writeView'=>$writeView,
252N/A 'notifyView'=>''}
252N/A };
252N/A if ($oid ne '') {
252N/A push @output, {'meta'=>{'directive'=>'view',
252N/A 'viewName'=>$viewName,
252N/A 'viewType'=>'included',
252N/A 'oid'=>$oid}};
252N/A } else {
252N/A for ($i = 0; $i < @$default_oids; $i++) {
252N/A push @output, {'meta'=>{'directive'=>'view',
252N/A 'viewName'=>$viewName,
252N/A 'viewType'=>'included',
252N/A 'oid'=>$default_oids->[$i]}};
252N/A }
252N/A }
252N/A return @output;
252N/A}
252N/A
252N/Asub expand_rousers
252N/A{
252N/A my ($configs, $default_oids) = @_;
252N/A my ($file, $lines, $i, $output, $line, $directive, @tokens);
252N/A my (@expanded);
252N/A for $file (keys %$configs) {
252N/A $lines = $configs->{$file};
252N/A $output=[];
252N/A for ($i = 0; $i < @$lines; $i++) {
252N/A $line = $lines->[$i];
252N/A if (! exists $line->{'meta'}->{'directive'}) {
252N/A next;
252N/A }
252N/A $directive = $line->{'meta'}->{'directive'};
252N/A if ($directive eq 'rouser' || $directive eq 'rwuser') {
252N/A # expand rocommunity directive
252N/A @expanded = expand_rouser($line, $default_oids);
252N/A splice @$lines, $i, 1, @expanded;
252N/A $i += $#expanded;
252N/A }
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub expand_rocommunities
252N/A{
252N/A my ($configs, $default_oids)= @_;
252N/A my ($file, $lines, $i, $output, $line, $directive, @tokens);
252N/A my (@expanded);
252N/A for $file (keys %$configs) {
252N/A $lines = $configs->{$file};
252N/A $output=[];
252N/A for ($i = 0; $i < @$lines; $i++) {
252N/A $line = $lines->[$i];
252N/A if (! exists $line->{'meta'}->{'directive'}) {
252N/A next;
252N/A }
252N/A
252N/A if ($line->{'meta'}->{'directive'} eq 'rocommunity' ||
252N/A $line->{'meta'}->{'directive'} eq 'rwcommunity') {
252N/A # expand rocommunity directive
252N/A @expanded = expand_rocommunity($line, $default_oids);
252N/A splice @$lines, $i, 1, @expanded;
252N/A $i += $#expanded;
252N/A }
252N/A }
252N/A }
252N/A}
252N/A
252N/A##############################################################################
252N/A# General configuration
252N/A
252N/Asub install_agentx_config
252N/A{
252N/A my (@lines) = get_lines('master', \%::SMA_CONFIGS);
252N/A if (@lines) {
252N/A if (grep (($lines[0]->{'meta'}->{'masterMode'} eq $_),
252N/A ('agentx', 'all', 'yes', 'on'))) {
252N/A # master mode is enabled anyway
252N/A } else {
252N/A # master mode was disabled!
252N/A log_message "AgentX mastering capability has been explicitly ".
252N/A "disabled in the SMA config - Aborting.\n", $lines[0];
252N/A exit 1;
252N/A }
252N/A } else {
252N/A # master mode has not been specified, add it.
252N/A log_message "Enabling agentX mastering for SMA.\n";
252N/A prepend_line({'meta'=>{'directive'=>'master', 'masterMode'=>'agentx'}});
252N/A }
252N/A @lines = get_lines('agentxTimeout', \%::SMA_CONFIGS);
252N/A if (@lines) {
252N/A if ($lines[0]->{'agentxTimeout'} < 2) {
252N/A $lines[0]->{'agentxTimeout'} = 2;
252N/A replace_line(\%::SMA_CONFIGS, $lines[0], $lines[0]);
252N/A }
252N/A } else {
252N/A prepend_line({'meta'=>{'directive'=>'agentxTimeout', 'agentxTimeout'=>2}});
252N/A }
252N/A @lines = get_lines('agentxRetries', \%::SMA_CONFIGS);
252N/A if (@lines) {
252N/A if ($lines[0]->{'agentxRetries'} < 4) {
252N/A $lines[0]->{'agentxRetries'} = 4;
252N/A replace_line(\%::SMA_CONFIGS, $lines[0], $lines[0]);
252N/A }
252N/A } else {
252N/A prepend_line({'meta'=>{'directive'=>'agentxRetries', 'agentxRetries'=>4}});
252N/A }
252N/A}
252N/A
252N/Asub check_agent_configs
252N/A{
252N/A my ($directive, $line);
252N/A for $directive ('agentgroup', 'agentuser', 'authtrapenable') {
252N/A my (@masf) = get_lines($directive, \%::MASF_CONFIGS);
252N/A my (@sma) = get_lines($directive, \%::SMA_CONFIGS);
252N/A if (@masf > 0 && @sma == 0) {
252N/A log_message "The following $directive directive was found in ".
252N/A "the MASF configuration but is not configured for SMA:\n";
252N/A log_message $masf[0]->{'new'}."\n";
252N/A
252N/A } elsif (@masf > 0 && @sma > 0 && $sma[0] ne $masf[0]) {
252N/A log_message "The following $directive directive was found in ".
252N/A "the MASF configuration but differs in the SMA configuration:\n";
252N/A log_message $masf[0]->{'new'}."\n";
252N/A }
252N/A for $line (@masf) {
252N/A # delete the line
252N/A replace_line(\%::MASF_CONFIGS, $line, {'meta'=>{}});
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub check_system_configs
252N/A{
252N/A my ($directive, $line);
252N/A for $directive ('syslocation', 'syscontact', 'sysname', 'sysservices') {
252N/A my (@masf) = get_lines($directive, \%::MASF_CONFIGS);
252N/A my (@sma) = get_lines($directive, \%::SMA_CONFIGS);
252N/A if (@masf > 0 && @sma == 0) {
252N/A log_message "The following $directive directive was found in ".
252N/A "the MASF configuration but is not configured for SMA:\n";
252N/A log_message $masf[0]->{'new'}."\n";
252N/A log_message "You may wish to set this parameter in the SMA ".
252N/A "configuration file after this script completes migration.\n";
252N/A
252N/A } elsif (@masf > 0 && @sma > 0 && $sma[0]->{'new'} ne $masf[0]->{'new'}) {
252N/A log_message "The following $directive directive was found in ".
252N/A "the MASF configuration but differs in the SMA configuration:\n";
252N/A log_message $masf[0]->{'new'}."\n";
252N/A log_message "You may wish to set this parameter in the SMA ".
252N/A "configuration file after this script completes migration.\n";
252N/A }
252N/A for $line (@masf) {
252N/A # delete the line
252N/A replace_line(\%::MASF_CONFIGS, $line, {'meta'=>{}});
252N/A }
252N/A }
252N/A}
252N/A
252N/Asub process_agentaddress
252N/A{
252N/A my ($line, $lines, @masfAgentAddress, $smaAgentAddress, $config);
252N/A (@masfAgentAddress) = get_lines ('agentaddress', \%::MASF_CONFIGS);
252N/A if (@masfAgentAddress == 0) {
252N/A log_message "No agentaddress directive found for MASF\n";
252N/A return;
252N/A }
252N/A
252N/A # if more than one MASF agentaddress line was specified then all but the
252N/A # last are ignored so we should delete them
252N/A while (@masfAgentAddress > 1) {
252N/A $line = shift @masfAgentAddress;
252N/A replace_line (\%::MASF_CONFIGS, $line, {'meta'=>{}});
252N/A }
252N/A
252N/A my (@smaTokens, @masfTokens);
252N/A ($smaAgentAddress) = get_lines ('agentaddress', \%::SMA_CONFIGS);
252N/A if (! defined $smaAgentAddress) {
252N/A log_message "SMA uses default 161 port\n";
252N/A @smaTokens = ('udp:161');
252N/A } else {
252N/A @smaTokens = parse_agentaddress ($smaAgentAddress->{'new'});
252N/A }
252N/A
252N/A if (defined $smaAgentAddress) {
252N/A $line = $smaAgentAddress;
252N/A $config = \%::SMA_CONFIGS;
252N/A } else {
252N/A $line = $masfAgentAddress[0];
252N/A $config = \%::MASF_CONFIGS;
252N/A }
252N/A
252N/A if ($::DISABLE_MASF_PORT && @masfAgentAddress) {
252N/A log_message "Disabling access via old MASF port\n";
252N/A delete $masfAgentAddress[0]->{'new'};
252N/A return;
252N/A }
252N/A
252N/A @masfTokens = parse_agentaddress ($masfAgentAddress[0]->{'new'});
252N/A
252N/A # MASF addresses must be a subset of SMA
252N/A my ($i, $j, $okToMigrate);
252N/A $okToMigrate = 1;
252N/A for $i (@masfTokens) {
252N/A if (grep(($i eq $_), @smaTokens) == 0) {
252N/A log_message "MASF port configuration for port $i conflicts with SMA\n";
252N/A $okToMigrate = 0;
252N/A }
252N/A }
252N/A
252N/A if (! $okToMigrate && ! $::USE_MASF_PORT && ! $::DISABLE_MASF_PORT) {
252N/A log_message "Unable to resolve conflict - aborting\n";
252N/A exit 1;
252N/A }
252N/A
252N/A if ($::USE_MASF_PORT) {
252N/A push @smaTokens, @masfTokens;
252N/A }
252N/A $line->{'new'} = 'agentaddress '.(join ',',@smaTokens);
252N/A replace_line($config, $line, $line);
252N/A return;
252N/A}
252N/A
252N/A##############################################################################
252N/A# Main section starts here
252N/A
252N/A# configure Getopt for CLIP compliance
252N/AGetopt::Long::Configure('bundling', 'require_order',
252N/A 'no_getopt_compat', 'no_auto_abbrev', 'no_ignore_case');
252N/A
252N/Amy ($selectCommunity, $selectUser, $useAgentPort, $trapFilter,
252N/A $masterTrapTarget, $version, $help);
252N/A$selectCommunity = 'error';
252N/A$selectUser = 'error';
252N/A$useAgentPort = 'error';
252N/A$trapFilter = 'add';
252N/A
252N/Amy $result = GetOptions(
252N/A 'i|ignore-unrecognized-directives'=>\$::IGNORE_UNRECOGNIZED_DIRECTIVES,
252N/A 's|skip-user'=>\$::IGNORE_ENGINEID,
252N/A 'y|select-community=s'=>\$selectCommunity,
252N/A 'u|select-user=s'=>\$selectUser,
252N/A 'p|use-agent-port=s'=>\$useAgentPort,
252N/A 't|trap-filter=s'=>\$trapFilter,
252N/A 'l|master-trap-target=s'=>\$masterTrapTarget,
252N/A 'c|no-community'=>\$::DONT_KEEP_V1V2C_USERS,
252N/A 'r|no-trap'=>\$::DONT_KEEP_TRAP_DESTS,
252N/A 'm|no-usmuser'=>\$::DONT_KEEP_V3_USERS,
252N/A 'n|dry-run'=>\$::DRY_RUN,
252N/A 'V|version'=>\$version,
252N/A 'help|?'=>\$help);
252N/A
252N/Aif (! $result) {
252N/A print STDERR "An unrecognized option was present.\n";
252N/A help();
252N/A}
252N/A
252N/Aif ($version) {
252N/A version();
252N/A}
252N/A
252N/A# no interactive mode
252N/A$::AUTOMATED = 1;
252N/A
252N/A$::KEEP_MASF_GROUPS = 0;
252N/A$::KEEP_SMA_GROUPS = 0;
252N/Aif ($selectCommunity eq 'agent') {
252N/A $::KEEP_MASF_GROUPS = 1;
252N/A} elsif ($selectCommunity eq 'master') {
252N/A $::KEEP_SMA_GROUPS = 1;
252N/A} elsif ($selectCommunity ne 'error') {
252N/A print STDERR "Invalid --select-community option $selectCommunity".
252N/A " specified.\n";
252N/A help();
252N/A}
252N/A
252N/A$::KEEP_MASF_USM_USERS = 0;
252N/A$::KEEP_SMA_USM_USERS = 0;
252N/Aif ($selectUser eq 'agent') {
252N/A $::KEEP_MASF_USM_USERS = 1;
252N/A} elsif ($selectUser eq 'master') {
252N/A $::KEEP_SMA_USM_USERS = 1;
252N/A} elsif ($selectUser ne 'error') {
252N/A print STDERR "Invalid --select-user option $selectUser".
252N/A " specified.\n";
252N/A help();
252N/A}
252N/A
252N/A$::USE_MASF_PORT = 0;
252N/A$::DISABLE_MASF_PORT = 0;
252N/Aif ($useAgentPort eq 'enable') {
252N/A $::USE_MASF_PORT = 1;
252N/A} elsif ($useAgentPort eq 'disable') {
252N/A $::DISABLE_MASF_PORT = 1;
252N/A} elsif ($useAgentPort ne 'error') {
252N/A print STDERR "Invalid --use-agent-port option $useAgentPort specified\n";
252N/A help();
252N/A}
252N/A
252N/Aif ($trapFilter eq 'none') {
252N/A $::NO_TRAP_FILTERS = 1;
252N/A} elsif ($trapFilter eq 'add') {
252N/A $::NO_TRAP_FILTERS = 0;
252N/A} else {
252N/A print STDERR "Invalid --trap-filter option $trapFilter\n";
252N/A help();
252N/A}
252N/A
252N/A$::EXTEND_SMA_FILTERS = 0;
252N/A$::KEEP_SNMP_TARGET_PARAMS = 0;
252N/Aif (defined $masterTrapTarget) {
252N/A if ($trapFilter eq 'none') {
252N/A print STDERR "--master-trap-target cannot be used with --trap-filter=none\n";
252N/A help();
252N/A }
252N/A if ($masterTrapTarget eq 'agent') {
252N/A $::EXTEND_SMA_FILTERS = 1;
252N/A } elsif ($masterTrapTarget eq 'master') {
252N/A $::KEEP_SNMP_TARGET_PARAMS = 1;
252N/A $::EXTEND_SMA_FILTERS = 1;
252N/A } else {
252N/A print STDERR "Invalid --master-trap-target option $masterTrapTarget specified.\n";
252N/A help();
252N/A }
252N/A}
252N/A
252N/Aif ($help) {
252N/A help();
252N/A}
252N/A
252N/A# set the umask before writing to the log file
252N/Aset_umask();
252N/Alog_message "masfcnv ".localtime()."\n\n";
252N/Aare_we_root();
252N/Astop_sma_running();
252N/Astop_masf_running();
252N/A
252N/A@::MASF_CONFIG_FILES = ("/etc/opt/SUNWmasf/conf/snmpd.conf");
252N/A$::MASF_PERSISTENT_FILE = "/var/opt/SUNWmasf/snmpd.dat";
252N/A$::MASF_PERSISTENT_DIR = "/var/opt/SUNWmasf";
252N/A
252N/A@::SMA_CONFIG_FILES = ("/usr/lib/net-snmp/snmpd.conf");
252N/A$::SMA_PERSISTENT_FILE = "/var/net-snmp/snmpd.conf";
252N/A$::SMA_PERSISTENT_DIR = "/var/net-snmp";
252N/Asma_config_sanity_check();
252N/Amasf_config_sanity_check();
252N/Aread_config_files();
252N/Asanity_check_config_files();
252N/Aadd_metadata();
252N/Ainstall_agentx_config();
252N/Aprocess_agentaddress();
252N/Aconvert_rwcommunities();
252N/Aexpand_rocommunities(\%::MASF_CONFIGS, [$ENTITY_MIB_OID, $SUNPLAT_MIB_OID]);
252N/Aexpand_rocommunities(\%::SMA_CONFIGS, [$INTERNET_OID]);
252N/Aconvert_rwusers();
252N/Aexpand_rousers(\%::MASF_CONFIGS, [$ENTITY_MIB_OID, $SUNPLAT_MIB_OID]);
252N/Aexpand_rousers(\%::SMA_CONFIGS, [$INTERNET_OID]);
252N/Aclean_group_membership();
252N/Aif (! $::DONT_KEEP_V1V2C_USERS) {
252N/A uniquify_securityNames('masf');
252N/A process_com2sec();
252N/A} else {
252N/A remove_v1v2c_users();
252N/A}
252N/Auniquify_groupNames('masf');
252N/Acheck_usm_securityNames();
252N/Aprocess_engineIDs();
252N/Aif (! $::DONT_KEEP_V3_USERS) {
252N/A process_usm_securityNames();
252N/A} else {
252N/A remove_v3_users();
252N/A}
252N/Auniquify_viewNames('masf');
252N/A
252N/Aprocess_trapcommunity(\%::MASF_CONFIGS);
252N/Aprocess_trapcommunity(\%::SMA_CONFIGS);
252N/Aif ($::DONT_KEEP_TRAP_DESTS) {
252N/A remove_trap_destinations();
252N/A}
252N/Acheck_duplicate_trap_destinations();
252N/Aif ($::NO_TRAP_FILTERS) {
252N/A # simplistic trap processing
252N/A # no further filtering
252N/A} else {
252N/A
252N/A if ($::EXTEND_SMA_FILTERS) {
252N/A # "master"
252N/A # if the administrator selects EXTEND_SMA_FILTERS and
252N/A # KEEP_SNMP_TARGET_PARAMS is selected then: MASF trap destinations are
252N/A # migrated using existing SMA targetParams, targetAddrs, filterProfiles
252N/A # if possible. SMA trap destinations keep existing targetParams and
252N/A # have filterProfiles updated to INCLUDE MASF traps. Targets present in
252N/A # both SMA and MASF configs end up receiving all traps with SMA params.
252N/A # 1. Update SMA filterProfiles to include MASF traps
252N/A # 2. Expand existing MASF trapsinks to targetAddrs, params, and profiles
252N/A # identifying overlapping trap destinations and using them where
252N/A # appropriate
252N/A
252N/A # "agent"
252N/A # if the administrator selects EXTEND_SMA_FILTERS and
252N/A # KEEP_SNMP_TARGET_PARAMS is not selected then: MASF trap destinations
252N/A # are migrated using MASF targetParams, targetAddrs, filterProfiles.
252N/A # All SMA trap destinations not in MASF use SMA params and have MASF
252N/A # traps INCLUDED. New params are created for targets present in both
252N/A # SMA and MASF which use tag specifically for MASF. Targets present in
252N/A # both SMA and MASF configs end up receiving all traps with MASF params.
252N/A # 1. Update SMA filterProfiles to include MASF traps
252N/A # 2. Expand existing MASF trapsinks to new targetAddrs, params,
252N/A # profiles, identifying overlapping trap destinations and profiles,
252N/A # transferring them to new SMA params and retain original profiles.
252N/A
252N/A # selecting KEEP_SNMP_TARGET_PARAMS without EXTEND_SMA_FILTERS is not an
252N/A # option
252N/A extend_sma_trap_filters();
252N/A }
252N/A # "add"
252N/A # if the administrator selects neither option then: All MASF trap
252N/A # configurations are translated to new params, targetAddrs, filters which
252N/A # have ONLY MASF traps included in the profile. Targets present in both
252N/A # MASF and SMA may receive duplicate traps, depending upon the SMA filter
252N/A # profile.
252N/A # 1. Expand existing MASF trapsinks to new targetAddrs, params, profiles.
252N/A process_trapsinks();
252N/A}
252N/Acheck_system_configs();
252N/Acheck_agent_configs();
252N/Aconvert_metadata();
252N/Aif (! $::DRY_RUN) {
252N/A backup_files();
252N/A remove_masf_persistent_file();
252N/A}
252N/Aif ($::DRY_RUN) {
252N/A print "Contents of ".$::SMA_CONFIG_FILES[0]."\n";
252N/A print "\n";
252N/A *FH = *STDOUT;
252N/A} else {
252N/A open (FH, "> ".$::SMA_CONFIG_FILES[0]) || die "Couldn't open file ".$::SMA_CONFIG_FILES[0]." for writing.\n";
252N/A}
252N/Amy ($l);
252N/Afor $l (@{$::ADDED_CONFIGS{'prepend'}}) {
252N/A print_line (\*FH, $l);
252N/A}
252N/Adump_config(\*FH, $::SMA_PERSISTENT_FILE, \%::SMA_CONFIGS);
252N/Adump_config(\*FH, $::MASF_PERSISTENT_FILE, \%::MASF_CONFIGS);
252N/Afor $l (@{$::ADDED_CONFIGS{'append'}}) {
252N/A print_line (\*FH, $l);
252N/A}
252N/Aif ($::DRY_RUN) {
252N/A print "=======================\n";
252N/A print "Contents of ".$::SMA_PERSISTENT_FILE."\n";
252N/A print "=======================\n";
252N/A} else {
252N/A close FH;
252N/A open (FH, "> ".$::SMA_PERSISTENT_FILE) || die "Couldn't open file ".$::SMA_PERSISTENT_FILE." for writing.\n";
252N/A}
252N/Adump_persistent_storage(\*FH, $::SMA_PERSISTENT_FILE, \%::SMA_CONFIGS);
252N/Adump_persistent_storage(\*FH, $::MASF_PERSISTENT_FILE, \%::MASF_CONFIGS);
252N/Aif (! $::DRY_RUN) {
252N/A close FH;
252N/A install_template_config_file();
252N/A install_new_wrapper_script();
252N/A}