|
1 # |
|
2 # Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. |
|
3 # |
|
4 # ident "@(#)migration.pl 1.5 03/06/26 SMI" |
|
5 # |
|
6 # $Id: masfcnv,v 1.3 2004/01/09 14:04:14 rr144420 Exp $ |
|
7 |
|
8 =head1 NAME |
|
9 |
|
10 masfcnv - SNMP configuration migration script |
|
11 |
|
12 =head1 SYNOPSIS |
|
13 |
|
14 masfcnv S<[ -cimnrs ]> S<[ -l agent|master ]> S<[ -p enable|disable|error ]> |
|
15 S<[ -t none|add ]> S<[ -u agent|master|error ]> S<[ -y agent|master|error ]> |
|
16 |
|
17 masfcnv [ -V ] |
|
18 |
|
19 masfcnv [ -? ] |
|
20 |
|
21 =head1 DESCRIPTION |
|
22 |
|
23 The masfcnv script is used to assist the system administrator in migrating an |
|
24 existing set of configuration files for the Sun SNMP Management Agent for Sun |
|
25 Fire and Netra Systems (MASF) to the Systems Management Agent (SMA). |
|
26 |
|
27 The script accepts as input the currently installed set of MASF and SMA |
|
28 configuration files and outputs a new set of SMA configuration files. Existing |
|
29 SMA configuration files are backed up by appending ".bak" to the filename. The |
|
30 administrator may choose to output the new configuration to the standard output |
|
31 instead of replacing the current configuration by specifying the -n option. |
|
32 |
|
33 The migration script must be run as the superuser and failure to do so will |
|
34 cause the script to exit with an error message. Before running the script the |
|
35 administrator should ensure that both the SMA and MASF agents are not running. |
|
36 If the agents are running they will be shut down by the script. |
|
37 |
|
38 The migration script will install a new startup script for the MASF agent in |
|
39 /etc/init.d and backup the old script. During migration, MASF will be |
|
40 configured as an AgentX subagent of SMA. All migration settings will be |
|
41 migrated to the SMA configuration file. |
|
42 |
|
43 The migration script will abort if any unrecognised directives are found in |
|
44 either the MASF configuration files or the SMA configuration files. This may |
|
45 be overridden with the -i option. If this option is selected, the behaviour is |
|
46 to retain unrecognised directives which were present in the SMA configuration, |
|
47 but remove those present in the MASF configuration. |
|
48 |
|
49 The migration script will then proceed to migrate access control and trap |
|
50 configuration. As a side-effect of running the migration script, the following |
|
51 directives may be expanded by the script into multiple directives with |
|
52 an equivalent interpretation: |
|
53 |
|
54 =over |
|
55 |
|
56 =item rwcommunity |
|
57 |
|
58 =item rocommunity |
|
59 |
|
60 =item rwuser |
|
61 |
|
62 =item rouser |
|
63 |
|
64 =item trapcommunity |
|
65 |
|
66 =item trapsink |
|
67 |
|
68 =item trap2sink |
|
69 |
|
70 =item informsink |
|
71 |
|
72 =back |
|
73 |
|
74 =head2 Access Control Migration |
|
75 |
|
76 Access control directives will be expanded into the equivalent com2sec, group, |
|
77 access and view directives. Existing group names will be renamed by prepending |
|
78 a prefix to avoid conflict with any which may already be defined in SMA. |
|
79 |
|
80 When migrating SNMPv1 or v2c access control, a conflict may occur if both MASF |
|
81 and SMA configuration files have defined access permissions for the same |
|
82 community and source address. The default behaviour is to abort with a |
|
83 message, unless the -y option specifies otherwise. If "-y agent" was specified |
|
84 then the MASF configuration will take precedence. If "-y master" was specified |
|
85 then the SMA configuration will be retained. |
|
86 |
|
87 When migrating USM configuration (SNMPv3), a conflict may occur if both SMA |
|
88 and MASF configurations define a user with the same securityName. If this |
|
89 occurs then the behaviour of the script is determined by the -u option. |
|
90 If "-u agent" has been selected then the configuration of the user defined in |
|
91 the MASF configuration files will be the one that is retained. Otherwise, if |
|
92 the "-u master" option has been selected, the one defined in the SMA |
|
93 configuration files will be retained. |
|
94 |
|
95 The migration script will by default attempt to migrate USM users from MASF to |
|
96 SMA. The script will determine whether there are any existing SNMPv3 users |
|
97 present in the SMA configuration and whether or not the default engineID has |
|
98 been overridden in the SMA configuration files. If neither of these are found to |
|
99 be the case then the any usmUser statements containing localised |
|
100 authentication keys can be migrated to SMA, along with the MASF engineID. This |
|
101 will result in the engineID of SMA master agent changing. |
|
102 |
|
103 If the script determines that there are existing SNMPv3 users or a manually |
|
104 configured engineID present in the SMA configuration, then only those users |
|
105 defined in createUser statements will be transferred. Those users which were |
|
106 defined in usmUser statements will be transferred but will have their |
|
107 passwords reset to a random value. The administrator is advised to notify |
|
108 their users of their new password and/or reset the password themselves by |
|
109 editing the newly-generated configuration file themselves. |
|
110 |
|
111 =head2 Trap/Inform Migration |
|
112 |
|
113 The migration script will perform a check to determine whether a trap |
|
114 destination defined for MASF is already specified in an existing SMA trapsink, |
|
115 trap2sink or informsink directive. If this is the case then the directive in |
|
116 the MASF configuration will be discarded to avoid duplicate traps/informs being |
|
117 received. |
|
118 |
|
119 trapsink, trap2sink and informsink directives specified in the existing SMA |
|
120 configuration are considered valid destinations for MASF traps/informs and will |
|
121 receive them from the MASF subagent after migration. |
|
122 |
|
123 If the "-t none" option was specified on the command line, then the migration |
|
124 script will carry over any remaining MASF trap/inform directives without |
|
125 modification. |
|
126 |
|
127 If the "-t add" option was specified (the default), then the migration script |
|
128 will expand any trapsink, trap2sink or informsink directives to use the |
|
129 TARGET-MIB and NOTIFICATION-MIB. The TARGET-MIB specifies targets using IP |
|
130 addresses, so it may be desirable to use the "-t none" option if, for example, |
|
131 the network allocates IP addresses to hostnames dynamically via DHCP. |
|
132 |
|
133 The expanded directives will define filters specific to the MASF agent so that |
|
134 traps from other subagents will not be received by migrated trap destinations. |
|
135 Existing filters present in the SMA configuration will by default not be |
|
136 modified and may or may not receive MASF traps depending upon the filters |
|
137 which were originally defined for them. |
|
138 |
|
139 If the -l option is specified, then any filters already defined in the |
|
140 TARGET-MIB and the NOTIFICATION-MIB for SMA will be extended to include traps |
|
141 from MASF. In the event that a trap destination is already configured in the |
|
142 TARGET-MIB with the same target address and community as an existing MASF |
|
143 trap/inform sink, a conflict will arise. |
|
144 |
|
145 If "-l agent" was specified and a conflict arises, then the migration script |
|
146 will use the target SNMP parameters (i.e. SNMP version and choise of |
|
147 trap/inform) defined by the MASF trap/informsink directive to send traps to |
|
148 this destination. Otherwise if the "-l master" option was specified, then the |
|
149 conflict will be resolved using the target SNMP parameters specified in the |
|
150 SMA configuration. |
|
151 |
|
152 =head2 Miscellaneous |
|
153 |
|
154 If the migration script encounters any of the following directives in the MASF |
|
155 configuration file and they are either not present or differ in the SMA |
|
156 configuration, the script will log a warning message: |
|
157 |
|
158 =over |
|
159 |
|
160 =item syslocation |
|
161 |
|
162 =item syscontact |
|
163 |
|
164 =item sysname |
|
165 |
|
166 =item sysservices |
|
167 |
|
168 =item agentgroup |
|
169 |
|
170 =item agentuser |
|
171 |
|
172 =item authtrapenable |
|
173 |
|
174 =back |
|
175 |
|
176 =head1 OPTIONS |
|
177 |
|
178 =over |
|
179 |
|
180 =item B<-?> |
|
181 |
|
182 =item B<--help> |
|
183 |
|
184 Displays usage information. |
|
185 |
|
186 =item B<-c> |
|
187 |
|
188 =item B<--no-community> |
|
189 |
|
190 Do not transfer v1/v2c communities |
|
191 |
|
192 =item B<-i> |
|
193 |
|
194 =item B<--ignore-unrecognized-directives> |
|
195 |
|
196 Continue processing if unrecognised directives are present. |
|
197 |
|
198 =item B<-l> I<agent|master> |
|
199 |
|
200 =item B<--master-trap-target>=I<agent|master> |
|
201 |
|
202 If 'agent' is specified then the existing SMA trap targets will be configured |
|
203 to receive traps that were previously sent to destinations for the Sun Fire |
|
204 SNMP agent. If 'master' is specified then the targets will be configured to |
|
205 receive Sun Fire SNMP traps but existing SNMP target parameters will be used. |
|
206 |
|
207 =item B<-m> |
|
208 |
|
209 =item B<--no-usmuser> |
|
210 |
|
211 Do not transfer usm (v3) users |
|
212 |
|
213 =item B<-n> |
|
214 |
|
215 =item B<--dry-run> |
|
216 |
|
217 Run the migration without modifying any files. If any error arises then |
|
218 continue processing. This can be used to determine the likely migration issues. |
|
219 |
|
220 =item B<-p> I<enable|disable|error> |
|
221 |
|
222 =item B<--use-agent-port>=I<enable|disable|error> |
|
223 |
|
224 Indicates whether the port originally used by the Sun Fire SNMP agent should be |
|
225 used by the SMA agent after migration (if the two agents are using different |
|
226 ports). If 'enable' is specified then the port used by the Sun Fire SNMP agent |
|
227 will also be used by the SMA agent after migration. If 'disable' is specified |
|
228 then the ports used by SMA will not be updated by the migration tool. If |
|
229 the 'error' option is specified and the SMA agent is not already using the same |
|
230 ports as those used by the original Sun Fire SNMP agent then an error will be |
|
231 reported and the migration process will be terminated. If no option is |
|
232 specified the default behaviour is equivalent to the 'error' flag. |
|
233 |
|
234 =item B<-r> |
|
235 |
|
236 =item B<--no-trap> |
|
237 |
|
238 Do not transfer trap destinations |
|
239 |
|
240 =item B<-s> |
|
241 |
|
242 =item B<--skip-user> |
|
243 |
|
244 If a user is found in the MASF configuration file that cannot be created in the |
|
245 new configuration due to a change in the engine ID, then output a message |
|
246 indicating that the user could not be migrated (needs to be manually recreated) |
|
247 and continue processing. If this option is not present then the migration tool |
|
248 will consider such a situation as an error and abort. |
|
249 |
|
250 =item B<-t> I<none|add> |
|
251 |
|
252 =item B<--trap-filter>=I<none|add> |
|
253 |
|
254 If 'none' is specified then the script will copy trap directives directly. The |
|
255 administrator may need to manually update the configuration file to ensure |
|
256 traps are only delivered to their intended destinations. If 'add' is specifed |
|
257 then trap filters will be constructed so that traps originating from the |
|
258 original Sun Fire SNMP agent are only delivered to the destinations that |
|
259 originally received them. 'add' is the default behaviour. |
|
260 |
|
261 =item B<-u> I<agent|master|error> |
|
262 |
|
263 =item B<--select-user>=I<agent|master|error> |
|
264 |
|
265 Specifies that if a user with the same name is found in both configuration |
|
266 files that the conflict is to be resolved using the specified configuration |
|
267 file as input. Selecting a user from a particular will also cause the group |
|
268 declaration for that user to be taken from the same file. If 'agent' is |
|
269 specified then the user will be taken from the configuration file for the Sun |
|
270 Fire SNMP Agent. If 'master' is specified then the user will be taken from the |
|
271 SMA configuration. Otherwise if 'error' is given, the script will terminate. |
|
272 If this option is not present then the default behaviour is equivalent to |
|
273 the 'error' flag. |
|
274 |
|
275 =item B<-V> |
|
276 |
|
277 =item B<--version> |
|
278 |
|
279 Display the version of this script. |
|
280 |
|
281 =item B<-y> I<agent|master|error> |
|
282 |
|
283 =item B<--select-community>=I<agent|master|error> |
|
284 |
|
285 Specifies that if a community and source (hostname, IP addr or range of IP |
|
286 addresses) is found to be conflicting in the two configurations, which |
|
287 combination should be selected when mapping to a security name. If 'agent' is |
|
288 specified then the community and source information will be taken from the |
|
289 configuration for the Sun Fire SNMP agent. If 'master' is specified it will be |
|
290 taken from the SMA agent. Otherwise if 'error' is specified an error will be |
|
291 reported and the migration will terminate. If this option is not present then |
|
292 the default behaviour is equivalent to the 'error' flag. |
|
293 |
|
294 =back |
|
295 |
|
296 =head1 EXIT STATUS |
|
297 |
|
298 The script will exit with 0 if migration was successful, non-zero if a problem |
|
299 occurred during migration. |
|
300 |
|
301 =head1 EXAMPLES |
|
302 |
|
303 For a simple migration which will fail if there are any potential conflicts: |
|
304 |
|
305 masfcnv |
|
306 |
|
307 To migrate the MASF configuration such that it will always succeed, MASF |
|
308 settings will override in the event of a conflict with SMA and access will |
|
309 still be provided on the original MASF port: |
|
310 |
|
311 masfcnv -is -l agent -p enable -u agent -y agent |
|
312 |
|
313 To attempt a dry run and migrate the configuration such that any conflicts |
|
314 will be resolved by retaining existing SMA settings: |
|
315 |
|
316 masfcnv -l master -u master -y master |
|
317 |
|
318 =head1 FILES |
|
319 |
|
320 =over |
|
321 |
|
322 =item /etc/sma/snmp/snmpd.conf |
|
323 |
|
324 =item /var/sma_snmp/snmpd.conf |
|
325 |
|
326 SMA configuration files |
|
327 |
|
328 =back |
|
329 |
|
330 =over |
|
331 |
|
332 =item /etc/opt/SUNWmasf/conf/snmpd.conf |
|
333 |
|
334 =item /var/opt/SUNWmasf/snmpd.dat |
|
335 |
|
336 MASF configuration files |
|
337 |
|
338 =back |
|
339 |
|
340 =over |
|
341 |
|
342 =item /tmp/sma_migration.log |
|
343 |
|
344 masfcnv log file |
|
345 |
|
346 =back |
|
347 |
|
348 =cut |
|
349 |
|
350 use strict; |
|
351 |
|
352 # Text::ParseWords requires 5.005 |
|
353 require 5.005; |
|
354 |
|
355 use Getopt::Long 2.17; |
|
356 use Text::ParseWords; |
|
357 use Net::hostent; |
|
358 use Socket; |
|
359 use Data::Dumper; |
|
360 use File::Copy; |
|
361 use Text::Wrap; |
|
362 |
|
363 ############################################################################## |
|
364 # global defaults |
|
365 |
|
366 # storage for new lines |
|
367 %::ADDED_CONFIGS = ('prepend'=>[], |
|
368 'append'=>[]); |
|
369 |
|
370 use vars qw ($INTERNET_OID |
|
371 $LOG_FILE |
|
372 $DATA_DIR |
|
373 $FILTER_TYPE_INCLUDED |
|
374 $FILTER_TYPE_EXCLUDED |
|
375 $ENTITY_MIB_OID |
|
376 $SUNPLAT_MIB_OID |
|
377 $SNMP_UDP_DOMAIN |
|
378 $DEFAULT_ROW_STATUS |
|
379 $DEFAULT_STORAGE_TYPE |
|
380 $MPMODEL_SNMPV1 |
|
381 $MPMODEL_SNMPV2C |
|
382 $MPMODEL_SNMPV2U |
|
383 $MPMODEL_SNMPV3 |
|
384 $SECURITY_MODEL_ANY |
|
385 $SECURITY_MODEL_SNMPV1 |
|
386 $SECURITY_MODEL_SNMPV2C |
|
387 $SECURITY_MODEL_USM |
|
388 $SECURITY_LEVEL_NOAUTHNOPRIV |
|
389 $SECURITY_LEVEL_AUTHNOPRIV |
|
390 $SECURITY_LEVEL_AUTHPRIV |
|
391 $NOTIFY_TYPE_TRAP |
|
392 $NOTIFY_TYPE_INFORM); |
|
393 # location where template files, etc. are stored. |
|
394 *LOG_FILE = \"/tmp/sma_migration.log"; |
|
395 *INTERNET_OID = \".1.3.6.1"; |
|
396 *DATA_DIR = \"/usr/lib/net_snmp"; |
|
397 *FILTER_TYPE_INCLUDED = \1; |
|
398 *FILTER_TYPE_EXCLUDED = \2; |
|
399 *ENTITY_MIB_OID = \".1.3.6.1.2.1.47"; |
|
400 *SUNPLAT_MIB_OID = \".1.3.6.1.4.1.42.2.70.101"; |
|
401 *SNMP_UDP_DOMAIN = \".1.3.6.1.6.1.1"; |
|
402 *DEFAULT_ROW_STATUS = \1; |
|
403 *DEFAULT_STORAGE_TYPE = \3; |
|
404 *MPMODEL_SNMPV1 = \0; |
|
405 *MPMODEL_SNMPV2C = \1; |
|
406 *MPMODEL_SNMPV2U = \2; |
|
407 *MPMODEL_SNMPV3 = \3; |
|
408 *SECURITY_MODEL_ANY = \0; |
|
409 *SECURITY_MODEL_SNMPV1 = \1; |
|
410 *SECURITY_MODEL_SNMPV2C = \2; |
|
411 *SECURITY_MODEL_USM = \3; |
|
412 *SECURITY_LEVEL_NOAUTHNOPRIV = \1; |
|
413 *SECURITY_LEVEL_AUTHNOPRIV = \2; |
|
414 *SECURITY_LEVEL_AUTHPRIV = \3; |
|
415 *NOTIFY_TYPE_TRAP = \1; |
|
416 *NOTIFY_TYPE_INFORM = \2; |
|
417 |
|
418 |
|
419 ############################################################################## |
|
420 # misc functions |
|
421 |
|
422 sub log_message |
|
423 { |
|
424 my ($msg, $line) = @_; |
|
425 if (defined $line && exists $line->{'file'} && exists |
|
426 $line->{'lineno'}) { |
|
427 $msg = $line->{'file'}.', line '.($line->{'lineno'} + 1). |
|
428 ': '.$msg; |
|
429 } |
|
430 $msg = wrap('', '', $msg); |
|
431 if ($::AUTOMATED) { |
|
432 open (LOG, ">> $LOG_FILE") || |
|
433 die "Couldn't open log file $LOG_FILE\n"; |
|
434 print LOG $msg; |
|
435 print STDERR $msg; |
|
436 close LOG; |
|
437 } else { |
|
438 print STDERR $msg; |
|
439 } |
|
440 } |
|
441 |
|
442 sub get_backup_filename |
|
443 { |
|
444 my ($fname) = @_; |
|
445 if ( -e $fname.'.bak') { |
|
446 my ($i) = 0; |
|
447 while ( -e $fname.".bak.$i" ) { |
|
448 $i++; |
|
449 } |
|
450 return $fname.".bak.$i"; |
|
451 } |
|
452 return $fname.".bak"; |
|
453 } |
|
454 |
|
455 sub backup_files |
|
456 { |
|
457 log_message "Backing up original files\n"; |
|
458 my ($f, $newf); |
|
459 for $f (@::MASF_CONFIG_FILES, $::MASF_PERSISTENT_FILE, @::SMA_CONFIG_FILES, |
|
460 $::SMA_PERSISTENT_FILE) { |
|
461 if (! -e $f) { |
|
462 next; |
|
463 } |
|
464 $newf = get_backup_filename($f); |
|
465 log_message "Backing up $f to $newf\n"; |
|
466 if (0 == copy $f, $newf) { |
|
467 log_message "Couldn't backup $f - aborting\n"; |
|
468 exit 1; |
|
469 } |
|
470 } |
|
471 } |
|
472 |
|
473 sub remove_masf_persistent_file |
|
474 { |
|
475 if (! -e $::MASF_PERSISTENT_FILE) { |
|
476 return; |
|
477 } |
|
478 log_message "Removing $::MASF_PERSISTENT_FILE\n"; |
|
479 if (0 == unlink $::MASF_PERSISTENT_FILE) { |
|
480 log_message "Couldn't remove MASF persistent storage file\n". |
|
481 "$::MASF_PERSISTENT_FILE - Aborting\n"; |
|
482 exit 1; |
|
483 } |
|
484 } |
|
485 |
|
486 sub version |
|
487 { |
|
488 my ($rev) = '$Revision: 1.3 $'; |
|
489 $rev=~s/^\$Revision: //; |
|
490 $rev=~s/ \$$//; |
|
491 print STDERR "$0 $rev\n". |
|
492 "Copyright 2003 Sun Microsystems, Inc.\n". |
|
493 "All rights reserved.\n". |
|
494 "Use is subject to license terms.\n"; |
|
495 exit 0; |
|
496 } |
|
497 |
|
498 sub stop_sma_running |
|
499 { |
|
500 `/etc/init.d/init.sma stop`; |
|
501 } |
|
502 |
|
503 sub stop_masf_running |
|
504 { |
|
505 `/etc/init.d/masfd stop`; |
|
506 if (($? >> 8) > 0) { |
|
507 log_message "Couldn't stop the MASF agent\n"; |
|
508 exit 1; |
|
509 } |
|
510 } |
|
511 |
|
512 sub set_umask |
|
513 { |
|
514 # only root should be able to read the config file |
|
515 umask 0077; |
|
516 } |
|
517 |
|
518 sub install_new_wrapper_script |
|
519 { |
|
520 log_message "Installing new MASF startup script\n"; |
|
521 |
|
522 my $pkgInstance='SUNWmasfr'; |
|
523 my @commands=("/usr/sbin/installf $pkgInstance /etc/init.d/masfd f 744 root sys", |
|
524 "/usr/sbin/installf $pkgInstance /etc/rc0.d/K40masfd=/etc/init.d/masfd l", |
|
525 "/usr/sbin/installf $pkgInstance /etc/rc1.d/K40masfd=/etc/init.d/masfd l", |
|
526 "/usr/sbin/installf $pkgInstance /etc/rc2.d/K40masfd=/etc/init.d/masfd l", |
|
527 "/usr/sbin/installf $pkgInstance /etc/rc3.d/S90masfd=/etc/init.d/masfd l", |
|
528 "/usr/sbin/installf $pkgInstance /etc/rcS.d/K40masfd=/etc/init.d/masfd l", |
|
529 "/usr/sbin/install -f /etc/init.d -m 0744 -u root -g sys $DATA_DIR/masfd", |
|
530 "/usr/sbin/installf -f $pkgInstance", |
|
531 "/usr/sbin/removef $pkgInstance /etc/rc3.d/S80masfd", |
|
532 "/usr/bin/rm /etc/rc3.d/S80masfd", |
|
533 "/usr/sbin/removef -f $pkgInstance" |
|
534 ); |
|
535 my $command; |
|
536 for $command (@commands) { |
|
537 `$command`; |
|
538 if ($? >> 8) { |
|
539 log_message "A problem occurred whilst installing the MASF startup ". |
|
540 "script\n"; |
|
541 exit 1; |
|
542 } |
|
543 } |
|
544 } |
|
545 |
|
546 sub install_template_config_file |
|
547 { |
|
548 if (copy($DATA_DIR.'/snmpd.conf', $::MASF_CONFIG_FILES[0]) == 0) { |
|
549 log_message "Couldn't copy template configuration file to ". |
|
550 $::MASF_CONFIG_FILES[0]."\n"; |
|
551 exit 1; |
|
552 } |
|
553 } |
|
554 |
|
555 sub are_we_root |
|
556 { |
|
557 if ($> != 0) { |
|
558 log_message "You are not running this as root.\n"; |
|
559 exit 1; |
|
560 } |
|
561 } |
|
562 |
|
563 sub sma_config_sanity_check |
|
564 { |
|
565 my ($files, $i); |
|
566 # check we can read the main config file |
|
567 if ( ! -r $::SMA_CONFIG_FILES[0] ) { |
|
568 log_message "Couldn't read SMA config file ". |
|
569 $::SMA_CONFIG_FILES[0]."\n"; |
|
570 exit 1; |
|
571 } |
|
572 for ($i = 0; $i < @::SMA_CONFIG_FILES; $i++) { |
|
573 if (! -r $::SMA_CONFIG_FILES[$i]) { |
|
574 splice @::SMA_CONFIG_FILES, $i--, 1; |
|
575 } |
|
576 } |
|
577 # check that if the persistent storage file isn't present, that there |
|
578 # aren't any stale backups indicating it failed to update it properly |
|
579 if ( ! -e $::SMA_PERSISTENT_FILE ) { |
|
580 $files = `/bin/ls $::SMA_PERSISTENT_DIR/sma.*.dat 2>/dev/null`; |
|
581 if ($files ne '') { |
|
582 log_message "Stale SMA agent config files found. The ". |
|
583 "SMA agent may not have been shut down cleanly.\n"; |
|
584 exit 1; |
|
585 } else { |
|
586 # Assume this is because the agent was never run |
|
587 log_message "WARNING: no SMA persistent storage file found\n"; |
|
588 } |
|
589 } |
|
590 } |
|
591 |
|
592 sub masf_config_sanity_check |
|
593 { |
|
594 my ($files, $i); |
|
595 # check we can read the main config file |
|
596 if ( ! -r $::MASF_CONFIG_FILES[0] ) { |
|
597 log_message "Couldn't read MASF config file ". |
|
598 $::MASF_CONFIG_FILES[0]."\n"; |
|
599 exit 1; |
|
600 } |
|
601 for ($i = 0; $i < @::MASF_CONFIG_FILES; $i++) { |
|
602 if (! -r $::MASF_CONFIG_FILES[$i]) { |
|
603 splice @::MASF_CONFIG_FILES, $i--, 1; |
|
604 } |
|
605 } |
|
606 # check that if the persistent storage file isn't present, that there |
|
607 # aren't any stale backups indicating it failed to update it properly |
|
608 if ( ! -e $::MASF_PERSISTENT_FILE ) { |
|
609 $files = `/bin/ls $::MASF_PERSISTENT_DIR/snmpd.*.dat 2>/dev/null`; |
|
610 if ($files ne '') { |
|
611 log_message "Stale MASF agent config files found. The MASF agent ". |
|
612 "may not have been shut down cleanly.\n"; |
|
613 exit 1; |
|
614 } else { |
|
615 # Assume this is because the agent was never run |
|
616 log_message "WARNING: no MASF persistent storage file found\n"; |
|
617 } |
|
618 } |
|
619 } |
|
620 |
|
621 sub hostnameToUDPDomain |
|
622 { |
|
623 my ($target) = @_; |
|
624 my ($hostname, $port, $hostent); |
|
625 my @dotted_decimal; |
|
626 ($hostname, $port) = ($target=~/^([^:]+):(\d+)$/); |
|
627 if ($port eq "") { |
|
628 $port = 162; |
|
629 } |
|
630 ($hostent) = gethostbyname($hostname); |
|
631 @dotted_decimal = unpack ('C4', $hostent->addr_list->[0]); |
|
632 return sprintf "0x%02x%02x%02x%02x%04x", @dotted_decimal, $port; |
|
633 |
|
634 } |
|
635 |
|
636 sub help |
|
637 { |
|
638 my ($name) = ($0=~/([^\/]*)$/); |
|
639 print STDERR "Usage: |
|
640 $name [ -cimnrs ] [ -l agent|master ] [ -p enable|disable|error ] |
|
641 [ -t none|add ] [ -u agent|master|error ] [ -y agent|master|error ] |
|
642 |
|
643 $name [ -V ] |
|
644 |
|
645 $name [ -? ] |
|
646 |
|
647 Migrates the configuration of the SNMP Agent for |
|
648 Sun Fire Servers to the SMA SNMP Agent |
|
649 |
|
650 Option Interpretation |
|
651 |
|
652 -? |
|
653 --help |
|
654 Display this help message. |
|
655 |
|
656 -c |
|
657 --no-community |
|
658 Do not transfer v1/v2c communities |
|
659 |
|
660 -i |
|
661 --ignore-unrecognized-directives |
|
662 Continue processing if unrecognised directives are present. |
|
663 |
|
664 -l agent|master |
|
665 --master-trap-target=agent|master |
|
666 If 'agent' is specified then the existing SMA trap targets will |
|
667 be configured to receive traps that were previously sent to |
|
668 destinations for the Sun Fire SNMP agent. If 'master' is |
|
669 specified then the targets will be configured to receive Sun |
|
670 Fire SNMP traps but existing SNMP target parameters will be used. This |
|
671 option may not be used with the \"-t none\" option. |
|
672 |
|
673 -m |
|
674 --no-usmuser |
|
675 Do not transfer usm (v3) users |
|
676 |
|
677 -n |
|
678 --dry-run |
|
679 Run the migration without modifying any files. If any error |
|
680 arises then continue processing. This can be used to determine the |
|
681 likely migration issues. |
|
682 |
|
683 -p enable|disable|error |
|
684 --use-agent-port=enable|disable|error |
|
685 Indicates whether the port originally used by the Sun Fire SNMP |
|
686 agent should be used by the SMA agent after migration (if the |
|
687 two agents are using different ports). If 'enable' is specified |
|
688 then the port used by the Sun Fire SNMP agent will also be used |
|
689 by the SMA agent after migration. If 'disable' is specified then |
|
690 the ports used by SMA will not be updated by the migration tool. |
|
691 If the 'error' option is specified and the SMA agent is not |
|
692 already using the same ports as those used by the original Sun |
|
693 Fire SNMP agent then an error will be reported and the migration |
|
694 process will be terminated. If no option is specified the default |
|
695 behaviour is equivalent to the 'error' flag. |
|
696 |
|
697 -r |
|
698 --no-trap |
|
699 Do not transfer trap destinations |
|
700 |
|
701 -s |
|
702 --skip-user |
|
703 If a user is found in the MASF configuration file that |
|
704 cannot be created in the new configuration due to a change |
|
705 in the engine ID, then output a message indicating that |
|
706 the user could not be migrated (needs to be manually |
|
707 recreated) and continue processing. If this option is not |
|
708 present then the migration tool will consider such a |
|
709 situation as an error and abort. |
|
710 |
|
711 -t none|add |
|
712 --trap-filter=none|add |
|
713 If 'none' is specified then the script will copy trap directives |
|
714 directly. The administrator may need to manually update the |
|
715 configuration file to ensure traps are only delivered to their |
|
716 intended destinations. If 'add' is specifed then trap filters |
|
717 will be constructed so that traps originating from the original |
|
718 Sun Fire SNMP agent are only delivered to the destinations that |
|
719 originally received them. 'add' is the default behaviour. |
|
720 |
|
721 -u agent|master|error |
|
722 --select-user=agent|master|error |
|
723 Specifies that if a user with the same name is found in both |
|
724 configuration files that the conflict is to be resolved using |
|
725 the specified configuration file as input. Selecting a user |
|
726 from a particular will also cause the group declaration for |
|
727 that user to be taken from the same file. If 'agent' is |
|
728 specified then the user will be taken from the configuration |
|
729 file for the Sun Fire SNMP Agent. If 'master' is specified then |
|
730 the user will be taken from the SMA configuration. Otherwise |
|
731 if 'error' is given, the script will terminate. If this option |
|
732 is not present then the default behaviour is equivalent to the |
|
733 'error' flag. |
|
734 |
|
735 -V |
|
736 --version |
|
737 Display the version of this script. |
|
738 |
|
739 -y agent|master|error |
|
740 --select-community=agent|master|error |
|
741 Specifies that if a community and source (hostname, IP addr |
|
742 or range of IP addresses) is found to be conflicting in the |
|
743 two configurations, which combination should be selected when |
|
744 mapping to a security name. If 'agent' is specified then the |
|
745 community and source information will be taken from the |
|
746 configuration for the Sun Fire SNMP agent. If 'master' is |
|
747 specified it will be taken from the SMA agent. Otherwise if |
|
748 'error' is specified an error will be reported and the |
|
749 migration will terminate. If this option is not present then |
|
750 the default behaviour is equivalent to the 'error' flag. |
|
751 |
|
752 "; |
|
753 exit 1; |
|
754 } |
|
755 |
|
756 %::SMA_CONFIGS = (); |
|
757 %::MASF_CONFIGS = (); |
|
758 sub strip_cr_nl |
|
759 { |
|
760 # remove \r and \n |
|
761 my ($lines, $i); |
|
762 for $lines (values %::SMA_CONFIGS) { |
|
763 for ($i = 0; $i < @$lines; $i++) { |
|
764 chomp $lines->[$i]; |
|
765 } |
|
766 } |
|
767 for $lines (values %::MASF_CONFIGS) { |
|
768 for ($i = 0; $i < @$lines; $i++) { |
|
769 chomp $lines->[$i]; |
|
770 } |
|
771 } |
|
772 } |
|
773 |
|
774 sub read_config_files |
|
775 { |
|
776 my ($i, @lines); |
|
777 for ($i = 0; $i < @::SMA_CONFIG_FILES; $i++) { |
|
778 open (FH, '< '.$::SMA_CONFIG_FILES[$i]) || do { |
|
779 log_message("Couldn't read config file ". |
|
780 $::SMA_CONFIG_FILES[$i]."\n"); |
|
781 exit 1; |
|
782 }; |
|
783 @lines=<FH>; |
|
784 close FH; |
|
785 $::SMA_CONFIGS{$::SMA_CONFIG_FILES[$i]} = [@lines]; |
|
786 } |
|
787 if (-e $::SMA_PERSISTENT_FILE) { |
|
788 open (FH, '< '.$::SMA_PERSISTENT_FILE) || do { |
|
789 log_message("Couldn't read config file ".$::SMA_PERSISTENT_FILE."\n"); |
|
790 exit 1; |
|
791 }; |
|
792 @lines=<FH>; |
|
793 close FH; |
|
794 $::SMA_CONFIGS{$::SMA_PERSISTENT_FILE} = [@lines]; |
|
795 } |
|
796 for ($i = 0; $i < @::MASF_CONFIG_FILES; $i++) { |
|
797 open (FH, '< '.$::MASF_CONFIG_FILES[$i]) || do { |
|
798 log_message("Couldn't read config file ". |
|
799 $::MASF_CONFIG_FILES[$i]."\n"); |
|
800 exit 1; |
|
801 }; |
|
802 @lines=<FH>; |
|
803 close FH; |
|
804 $::MASF_CONFIGS{$::MASF_CONFIG_FILES[$i]} = [@lines]; |
|
805 } |
|
806 if (-e $::MASF_PERSISTENT_FILE) { |
|
807 open (FH, '< '.$::MASF_PERSISTENT_FILE) || do { |
|
808 log_message("Couldn't read config file ". |
|
809 $::MASF_PERSISTENT_FILE."\n"); |
|
810 exit 1; |
|
811 }; |
|
812 @lines=<FH>; |
|
813 close FH; |
|
814 $::MASF_CONFIGS{$::MASF_PERSISTENT_FILE} = [@lines]; |
|
815 } |
|
816 strip_cr_nl(); |
|
817 } |
|
818 |
|
819 sub prompt_yes_no |
|
820 { |
|
821 my ($prompt, $default) = @_; |
|
822 my $response = ''; |
|
823 print STDOUT $prompt," [".$default."]:"; |
|
824 $response = <STDIN>; |
|
825 chomp $response; |
|
826 if ($response eq '') { |
|
827 $response = $default; |
|
828 } |
|
829 while (uc($response)!~/^Y|N/) { |
|
830 print STDERR "Response must be (y)es or (n)o:"; |
|
831 $response = <STDIN>; |
|
832 chomp $response; |
|
833 } |
|
834 return $response=~/^[yY]/ ? 'yes' : 'no'; |
|
835 } |
|
836 |
|
837 sub prompt |
|
838 { |
|
839 my ($prompt, $default, $options) = @_; |
|
840 my $response = ''; |
|
841 print STDOUT $prompt," [".$default."]:"; |
|
842 $response = <STDIN>; |
|
843 chomp $response; |
|
844 if ($response eq '') { |
|
845 $response = $default; |
|
846 } |
|
847 while (scalar (grep $response eq $_, @$options) != 1) { |
|
848 print STDERR "Invalid response:"; |
|
849 $response = <STDIN>; |
|
850 chomp $response; |
|
851 } |
|
852 return $response; |
|
853 } |
|
854 |
|
855 sub parse_agentaddress |
|
856 { |
|
857 my ($line)=@_; |
|
858 my ($directive, $addresses)=($line=~/^\s*(agentaddress)\s+(.*\S)\s*$/); |
|
859 my ($addr, $spec, @addrs, $has_transport_specifier); |
|
860 @addrs=split /,/,$addresses; |
|
861 foreach $addr (@addrs) { |
|
862 $has_transport_specifier=($addr=~/:/); |
|
863 if (! $has_transport_specifier) { |
|
864 if ($addr=~/^\//) { |
|
865 $spec = "unix"; |
|
866 } else { |
|
867 $spec = "udp"; |
|
868 } |
|
869 $addr = $spec.':'.$addr; |
|
870 } |
|
871 } |
|
872 return @addrs; |
|
873 } |
|
874 |
|
875 sub parse_config_line |
|
876 { |
|
877 my ($line)=@_; |
|
878 my @words; |
|
879 # strip whitespace |
|
880 $line=~s/^\s*//; |
|
881 $line=~s/\s*$//; |
|
882 # check to see if comment |
|
883 if ((substr $line, 0, 1) eq '#') { |
|
884 return ('', ()); |
|
885 } |
|
886 @words = &parse_line('\s+', 0, $line); |
|
887 if (! defined $words[0]) { |
|
888 $words[0] = ''; |
|
889 } |
|
890 return @words; |
|
891 } |
|
892 |
|
893 sub sanity_check_config_files |
|
894 { |
|
895 my @smaTokens = ( |
|
896 'master', |
|
897 'agentxTimeout', |
|
898 'agentxRetries', |
|
899 'agentxPingInterval', |
|
900 'targetParams', |
|
901 'targetAddr', |
|
902 'snmpNotifyFilterProfileTable', |
|
903 'snmpNotifyTable', |
|
904 'snmpNotifyFilterTable' |
|
905 ); |
|
906 my @commonTokens = ( |
|
907 'rocommunity', |
|
908 'rwcommunity', |
|
909 'rouser', |
|
910 'rwuser', |
|
911 'agentaddress', |
|
912 'trapsink', |
|
913 'trap2sink', |
|
914 'informsink', |
|
915 'trapcommunity', |
|
916 'com2sec', |
|
917 'group', |
|
918 'access', |
|
919 'view', |
|
920 'engineID', |
|
921 'createUser', |
|
922 'agentgroup', |
|
923 'agentuser', |
|
924 'authtrapenable', |
|
925 'syslocation', |
|
926 'syscontact', |
|
927 'sysname', |
|
928 'sysservices', |
|
929 'engineBoots', |
|
930 'oldEngineID', |
|
931 'usmUser' |
|
932 ); |
|
933 my ($file, $i, $j, $directive, @tokens, $found, $warned, $answer); |
|
934 # check sma config files |
|
935 $warned = 0; |
|
936 for $file (keys %::SMA_CONFIGS) { |
|
937 for ($i = 0; $i < @{$::SMA_CONFIGS{$file}}; $i++) { |
|
938 $found = 0; |
|
939 ($directive, @tokens) = parse_config_line($::SMA_CONFIGS{$file}->[$i]); |
|
940 if ($directive eq '') { |
|
941 next; |
|
942 } |
|
943 |
|
944 for ($j = 0; $j < @smaTokens; $j++) { |
|
945 if ($directive eq $smaTokens[$j]) { |
|
946 $found = 1; |
|
947 last; |
|
948 } |
|
949 } |
|
950 if ($found) { |
|
951 next; |
|
952 } |
|
953 for ($j = 0; $j < @commonTokens; $j++) { |
|
954 if ($directive eq $commonTokens[$j]) { |
|
955 $found = 1; |
|
956 last; |
|
957 } |
|
958 } |
|
959 if ($found) { |
|
960 next; |
|
961 } |
|
962 # token was not recognised |
|
963 log_message("WARNING: Unrecognised token ".$directive. |
|
964 " found in file ".$file." at line ".($i + 1)."\n"); |
|
965 $warned = 1; |
|
966 } |
|
967 } |
|
968 for $file (keys %::MASF_CONFIGS) { |
|
969 for ($i = 0; $i < @{$::MASF_CONFIGS{$file}}; $i++) { |
|
970 $found = 0; |
|
971 ($directive, @tokens) = parse_config_line($::MASF_CONFIGS{$file}->[$i]); |
|
972 if ($directive eq '') { |
|
973 next; |
|
974 } |
|
975 |
|
976 for ($j = 0; $j < @commonTokens; $j++) { |
|
977 if ($directive eq $commonTokens[$j]) { |
|
978 $found = 1; |
|
979 last; |
|
980 } |
|
981 } |
|
982 if ($found) { |
|
983 next; |
|
984 } |
|
985 # token was not recognised |
|
986 log_message("WARNING: Unrecognised token ".$directive. |
|
987 " found in file ".$file." at line ".($i + 1)."\n"); |
|
988 $warned = 1; |
|
989 # remove the unrecognised token |
|
990 splice @{$::MASF_CONFIGS{$file}}, $i--, 1; |
|
991 } |
|
992 } |
|
993 if ($warned && ! $::IGNORE_UNRECOGNIZED_DIRECTIVES) { |
|
994 if ($::AUTOMATED) { |
|
995 log_message("Unrecognised tokens found in configuration ". |
|
996 "file(s) - aborting\n"); |
|
997 exit 1; |
|
998 } else { |
|
999 $answer = prompt_yes_no("Unrecognised tokens were found. Continue?", 'n'); |
|
1000 if ($answer eq 'no') { |
|
1001 exit 1; |
|
1002 } |
|
1003 } |
|
1004 } |
|
1005 } |
|
1006 |
|
1007 sub print_line |
|
1008 { |
|
1009 my ($fh, $line) = @_; |
|
1010 if (exists $line->{'orig'} && exists $line->{'new'}) { |
|
1011 if ($line->{'orig'} ne $line->{'new'}) { |
|
1012 print $fh "# ### CHANGED BY $0 ###\n"; |
|
1013 print $fh '# ',$line->{'orig'},"\n"; |
|
1014 if (exists $line->{'comment'}) { |
|
1015 print $fh $line->{'comment'},"\n"; |
|
1016 } |
|
1017 print $fh $line->{'new'},"\n"; |
|
1018 } else { |
|
1019 print $fh $line->{'orig'},"\n"; |
|
1020 } |
|
1021 } elsif (exists $line->{'new'}) { |
|
1022 if (exists $line->{'comment'}) { |
|
1023 print $fh $line->{'comment'},"\n"; |
|
1024 } |
|
1025 print $fh $line->{'new'},"\n"; |
|
1026 } |
|
1027 |
|
1028 } |
|
1029 |
|
1030 @::SMA_PERSISTENT_FILE_TOKENS = ( |
|
1031 'targetParams', 'targetAddr', |
|
1032 'snmpNotifyFilterProfileTable', 'snmpNotifyTable', |
|
1033 'snmpNotifyFilterTable', 'engineBoots', 'usmUser', 'oldEngineID', |
|
1034 'createUser'); |
|
1035 |
|
1036 # extract those directives destined for persistent storage |
|
1037 sub dump_persistent_storage |
|
1038 { |
|
1039 my ($file, $persistent_file, $config) = @_; |
|
1040 #list of tokens which should be in persistent storage |
|
1041 my ($f, $l, $lines); |
|
1042 for $f (keys %$config) { |
|
1043 print $file "# ### IMPORTED FROM $f ###\n\n"; |
|
1044 for $l (@{$config->{$f}}) { |
|
1045 if (! exists $l->{'new'}) { |
|
1046 next; |
|
1047 } |
|
1048 my ($directive, @toks) = parse_config_line($l->{'new'}); |
|
1049 if ($directive) { |
|
1050 my (@match) = grep ($_ eq $directive, @::SMA_PERSISTENT_FILE_TOKENS); |
|
1051 if (@match == 0) { |
|
1052 # skip this line |
|
1053 next; |
|
1054 } |
|
1055 } elsif ($f ne $persistent_file) { |
|
1056 # skip all comments/blank lines which are not in the persistent |
|
1057 # storage file |
|
1058 next; |
|
1059 } |
|
1060 print_line($file, $l); |
|
1061 } |
|
1062 } |
|
1063 } |
|
1064 |
|
1065 sub dump_config |
|
1066 { |
|
1067 my ($file, $persistent_file, $config) = @_; |
|
1068 #list of tokens which should be in persistent storage |
|
1069 my ($f, $l, $lines); |
|
1070 for $f (keys %$config) { |
|
1071 print $file "# ### IMPORTED FROM $f ###\n\n"; |
|
1072 for $l (@{$config->{$f}}) { |
|
1073 if (! exists $l->{'new'}) { |
|
1074 next; |
|
1075 } |
|
1076 my ($directive, @toks) = parse_config_line($l->{'new'}); |
|
1077 if ($directive) { |
|
1078 my (@match) = grep ($_ eq $directive, @::SMA_PERSISTENT_FILE_TOKENS); |
|
1079 if (@match > 0) { |
|
1080 if ($f ne $persistent_file && exists $l->{'orig'}) { |
|
1081 print $file "# moved to $::SMA_PERSISTENT_FILE >>> ". |
|
1082 $l->{'orig'}."\n"; |
|
1083 } |
|
1084 # skip this line |
|
1085 next; |
|
1086 } |
|
1087 } elsif ($f eq $persistent_file) { |
|
1088 # skip all comments/blank lines which are not in the persistent |
|
1089 # storage file |
|
1090 next; |
|
1091 } |
|
1092 print_line($file, $l); |
|
1093 } |
|
1094 } |
|
1095 } |
|
1096 |
|
1097 sub set_union { |
|
1098 my ($seta, $setb) = @_; |
|
1099 my ($i, $j, $found, @out); |
|
1100 for $i (@$seta, @$setb) { |
|
1101 $found = 0; |
|
1102 for $j (@out) { |
|
1103 if ($j eq $i) { |
|
1104 $found = 1; |
|
1105 } |
|
1106 } |
|
1107 if (! $found) { |
|
1108 push @out, $i; |
|
1109 } |
|
1110 } |
|
1111 return @out; |
|
1112 } |
|
1113 |
|
1114 sub in_addr_to_number |
|
1115 { |
|
1116 my ($in_addr) = @_; |
|
1117 my ($i, $N) = (0, 0); |
|
1118 my (@n) = (unpack 'C4', $in_addr); |
|
1119 for ($i = 0; $i < @n; $i++) { |
|
1120 $N = $N << 8; |
|
1121 $N += $n[$i]; |
|
1122 } |
|
1123 return $N; |
|
1124 } |
|
1125 |
|
1126 sub splice_line |
|
1127 { |
|
1128 my ($config, $line, $length, $offset, @lines) = @_; |
|
1129 my ($i, $f); |
|
1130 for $i (@lines) { |
|
1131 # mark all the lines as changed |
|
1132 $i->{'changed'} = undef; |
|
1133 } |
|
1134 for $f (values %$config) { |
|
1135 for ($i = 0; $i < @$f; $i++) { |
|
1136 if ($f->[$i] eq $line) { |
|
1137 if (@lines) { |
|
1138 splice @$f, $i + $offset, $length, @lines; |
|
1139 } else { |
|
1140 splice @$f, $i + $offset, $length; |
|
1141 } |
|
1142 return; |
|
1143 } |
|
1144 } |
|
1145 } |
|
1146 } |
|
1147 |
|
1148 sub prepend_line { |
|
1149 my ($line) = @_; |
|
1150 $line->{'changed'} = undef; |
|
1151 push @{$::ADDED_CONFIGS{'prepend'}}, $line; |
|
1152 } |
|
1153 |
|
1154 sub append_line { |
|
1155 my ($line) = @_; |
|
1156 $line->{'changed'} = undef; |
|
1157 push @{$::ADDED_CONFIGS{'append'}}, $line; |
|
1158 } |
|
1159 |
|
1160 sub replace_line { |
|
1161 my ($config, $line, @lines) = @_; |
|
1162 $line->{'meta'} = $lines[0]->{'meta'}; |
|
1163 if (exists $lines[0]->{'new'}) { |
|
1164 $line->{'new'} = $lines[0]->{'new'}; |
|
1165 } else { |
|
1166 delete $line->{'new'}; |
|
1167 } |
|
1168 $lines[0] = $line; |
|
1169 splice_line($config, $line, 1, 0, @lines); |
|
1170 } |
|
1171 |
|
1172 sub insert_lines { |
|
1173 my ($config, $line, $after, @lines) = @_; |
|
1174 my ($offset) = ($after ? 1 : 0); |
|
1175 splice_line($config, $line, 0, $offset, @lines); |
|
1176 } |
|
1177 |
|
1178 sub get_lines |
|
1179 { |
|
1180 my ($directive, $config)=@_; |
|
1181 my ($line, $lines, @matches); |
|
1182 for $lines (values %$config) { |
|
1183 for $line (@$lines) { |
|
1184 if (exists $line->{'meta'}->{'directive'} && |
|
1185 $line->{'meta'}->{'directive'} eq $directive) { |
|
1186 push @matches, $line; |
|
1187 } |
|
1188 } |
|
1189 } |
|
1190 return @matches; |
|
1191 } |
|
1192 |
|
1193 ############################################################################## |
|
1194 # Traps |
|
1195 |
|
1196 sub remove_trap_destinations |
|
1197 { |
|
1198 my (@sinkLines) = (get_lines('trapsink', \%::MASF_CONFIGS), |
|
1199 get_lines('trap2sink', \%::MASF_CONFIGS), |
|
1200 get_lines('informsink', \%::MASF_CONFIGS)); |
|
1201 my ($line); |
|
1202 for $line (@sinkLines) { |
|
1203 replace_line(\%::MASF_CONFIGS, $line, {'meta'=>{}}); |
|
1204 } |
|
1205 } |
|
1206 |
|
1207 sub get_filters |
|
1208 { |
|
1209 my ($keys, $configs)=@_; |
|
1210 my ($f, $l, @filters); |
|
1211 for $f (values %$configs) { |
|
1212 for $l (@$f) { |
|
1213 if (! exists $l->{'meta'}->{'directive'} || |
|
1214 ($l->{'meta'}->{'directive'} ne 'snmpNotifyFilterTable')) { |
|
1215 next; |
|
1216 } |
|
1217 if (exists $keys->{'profileName'} && |
|
1218 $l->{'meta'}->{'profileName'} ne $keys->{'profileName'}) |
|
1219 { |
|
1220 next; |
|
1221 } |
|
1222 push @filters, $l; |
|
1223 } |
|
1224 } |
|
1225 return @filters; |
|
1226 } |
|
1227 |
|
1228 sub get_filterProfiles |
|
1229 { |
|
1230 my ($keys, $configs)=@_; |
|
1231 my ($f, $l, @targetAddrs); |
|
1232 for $f (values %$configs) { |
|
1233 for $l (@$f) { |
|
1234 if (! exists $l->{'meta'}->{'directive'} || |
|
1235 ($l->{'meta'}->{'directive'} ne 'snmpNotifyFilterProfileTable')) { |
|
1236 next; |
|
1237 } |
|
1238 if (exists $keys->{'paramName'} && |
|
1239 $l->{'meta'}->{'paramName'} ne $keys->{'paramName'}) { |
|
1240 next; |
|
1241 } |
|
1242 if (exists $keys->{'profileName'} && |
|
1243 $l->{'meta'}->{'profileName'} ne $keys->{'profileName'}) |
|
1244 { |
|
1245 next; |
|
1246 } |
|
1247 push @targetAddrs, $l; |
|
1248 } |
|
1249 } |
|
1250 return @targetAddrs; |
|
1251 } |
|
1252 |
|
1253 sub tag_in_taglist |
|
1254 { |
|
1255 my ($tag, $taglist) = @_; |
|
1256 my (@tags) = split /[ \t\r\n]/,$taglist; |
|
1257 my ($t); |
|
1258 for $t (@tags) { |
|
1259 if ($t eq $tag) { |
|
1260 return 1; |
|
1261 } |
|
1262 } |
|
1263 return 0; |
|
1264 } |
|
1265 |
|
1266 sub notifyName_exists |
|
1267 { |
|
1268 my ($name) = @_; |
|
1269 my ($file, $line, $meta); |
|
1270 for $file (values %::MASF_CONFIGS, values %::SMA_CONFIGS) { |
|
1271 for $line (@$file) { |
|
1272 $meta=$line->{'meta'}; |
|
1273 if (exists $meta->{'notifyName'} && |
|
1274 $meta->{'notifyName'} eq $name) { |
|
1275 return 1; |
|
1276 } |
|
1277 } |
|
1278 } |
|
1279 return 0; |
|
1280 } |
|
1281 |
|
1282 sub tag_exists |
|
1283 { |
|
1284 my ($tag) = @_; |
|
1285 my ($file, $line, $meta); |
|
1286 for $file (values %::MASF_CONFIGS, values %::SMA_CONFIGS) { |
|
1287 for $line (@$file) { |
|
1288 $meta = $line->{'meta'}; |
|
1289 if (exists $meta->{'tagList'} && |
|
1290 tag_in_taglist ($tag, $meta->{'tagList'})) { |
|
1291 return 1; |
|
1292 } |
|
1293 if (exists $meta->{'notifyTag'} && |
|
1294 $tag eq $meta->{'notifyTag'}) { |
|
1295 return 1; |
|
1296 } |
|
1297 } |
|
1298 } |
|
1299 return 0; |
|
1300 } |
|
1301 |
|
1302 sub get_new_profileName |
|
1303 { |
|
1304 my ($i) = (0); |
|
1305 my ($try) = ('masfProfile'.$i); |
|
1306 while (profileName_exists($try)) { |
|
1307 $i++; |
|
1308 $try = 'masfProfile'.$i; |
|
1309 } |
|
1310 if (length $try > 32) { |
|
1311 log_message "Unable to generate unique profileName\n"; |
|
1312 exit 1; |
|
1313 } |
|
1314 return $try; |
|
1315 } |
|
1316 |
|
1317 sub generate_notify_tags |
|
1318 { |
|
1319 my ($prefix) = @_; |
|
1320 my ($i) = (0); |
|
1321 while (tag_exists ($prefix.$i) || |
|
1322 notifyName_exists ($prefix.$i)) { |
|
1323 $i++; |
|
1324 } |
|
1325 if (length ($prefix.$i) > 255) { |
|
1326 log_message "Unable to generate valid tag for prefix ".$prefix."\n"; |
|
1327 exit 1; |
|
1328 } |
|
1329 return $prefix.$i; |
|
1330 } |
|
1331 |
|
1332 sub get_new_paramName |
|
1333 { |
|
1334 my ($i) = (0); |
|
1335 while (paramName_exists('masfParam'.$i)) { |
|
1336 $i++; |
|
1337 } |
|
1338 if (length 'masfParam'.$i > 32) { |
|
1339 log_message "Unable to generate unique paramName.\n"; |
|
1340 exit 1; |
|
1341 } |
|
1342 return 'masfParam'.$i; |
|
1343 } |
|
1344 |
|
1345 sub get_new_targetName |
|
1346 { |
|
1347 my ($host)=@_; |
|
1348 my ($i)=(0); |
|
1349 my ($try)=('masfTarget'.$i.$host); |
|
1350 while (targetName_exists($try) || length $try > 32) { |
|
1351 if (length $try > 32) { |
|
1352 chop $host; |
|
1353 if (length $host == 0) { |
|
1354 log_message "Unable to generate unique targetName\n"; |
|
1355 exit 1; |
|
1356 } |
|
1357 } else { |
|
1358 $i++; |
|
1359 } |
|
1360 $try = 'masfTarget'.$i.$host; |
|
1361 } |
|
1362 return $try; |
|
1363 } |
|
1364 |
|
1365 sub paramName_exists |
|
1366 { |
|
1367 my ($paramName) = @_; |
|
1368 my ($keys) = ({'paramName'=>$paramName}); |
|
1369 my (@lines) = (get_targetParams($keys, \%::SMA_CONFIGS), |
|
1370 get_targetParams($keys, \%::MASF_CONFIGS), |
|
1371 get_targetAddrs($keys, \%::SMA_CONFIGS), |
|
1372 get_targetAddrs($keys, \%::MASF_CONFIGS)); |
|
1373 if (@lines) { |
|
1374 return 1; |
|
1375 } else { |
|
1376 return 0; |
|
1377 } |
|
1378 } |
|
1379 |
|
1380 sub profileName_exists |
|
1381 { |
|
1382 my ($name) = @_; |
|
1383 my ($file, $line, $meta); |
|
1384 for $file (values %::MASF_CONFIGS, values %::SMA_CONFIGS) { |
|
1385 for $line (@$file) { |
|
1386 $meta=$line->{'meta'}; |
|
1387 if (exists $meta->{'profileName'} && |
|
1388 $meta->{'profileName'} eq $name) { |
|
1389 return 1; |
|
1390 } |
|
1391 } |
|
1392 } |
|
1393 return 0; |
|
1394 } |
|
1395 |
|
1396 sub targetName_exists |
|
1397 { |
|
1398 my ($targetName) = @_; |
|
1399 my ($keys) = ({'targetName'=>$targetName}); |
|
1400 my (@lines) = (get_targetAddrs($keys, \%::SMA_CONFIGS), |
|
1401 get_targetAddrs($keys, \%::MASF_CONFIGS)); |
|
1402 if (@lines) { |
|
1403 return 1; |
|
1404 } else { |
|
1405 return 0; |
|
1406 } |
|
1407 } |
|
1408 |
|
1409 # get all target addresses with the specified keys |
|
1410 sub get_targetAddrs |
|
1411 { |
|
1412 my ($keys, $configs)=@_; |
|
1413 my ($f, $l, @targetAddrs); |
|
1414 for $f (values %$configs) { |
|
1415 for $l (@$f) { |
|
1416 if (! exists $l->{'meta'}->{'directive'} || |
|
1417 ($l->{'meta'}->{'directive'} ne 'targetAddr')) { |
|
1418 next; |
|
1419 } |
|
1420 if (exists $keys->{'paramName'} && |
|
1421 $l->{'meta'}->{'paramName'} ne $keys->{'paramName'}) { |
|
1422 next; |
|
1423 } |
|
1424 if (exists $keys->{'TDomain'} && |
|
1425 $l->{'meta'}->{'TDomain'} ne $keys->{'TDomain'}) |
|
1426 { |
|
1427 next; |
|
1428 } |
|
1429 if (exists $keys->{'TAddress'} && |
|
1430 $l->{'meta'}->{'TAddress'} ne $keys->{'TAddress'}) |
|
1431 { |
|
1432 next; |
|
1433 } |
|
1434 if (exists $keys->{'targetName'} && |
|
1435 $l->{'meta'}->{'targetName'} ne $keys->{'targetName'}) |
|
1436 { |
|
1437 next; |
|
1438 } |
|
1439 push @targetAddrs, $l; |
|
1440 } |
|
1441 } |
|
1442 return @targetAddrs; |
|
1443 } |
|
1444 |
|
1445 # get all target parameters with the specified keys |
|
1446 sub get_targetParams |
|
1447 { |
|
1448 my ($keys, $configs)=@_; |
|
1449 my ($f, $l, @targetParams); |
|
1450 for $f (values %$configs) { |
|
1451 for $l (@$f) { |
|
1452 if (! exists $l->{'meta'}->{'directive'} || |
|
1453 ($l->{'meta'}->{'directive'} ne 'targetParams')) { |
|
1454 next; |
|
1455 } |
|
1456 if (exists $keys->{'paramName'} && |
|
1457 $l->{'meta'}->{'paramName'} ne $keys->{'paramName'}) { |
|
1458 next; |
|
1459 } |
|
1460 if (exists $keys->{'securityModel'} && |
|
1461 $l->{'meta'}->{'securityModel'} ne $keys->{'securityModel'}) |
|
1462 { |
|
1463 next; |
|
1464 } |
|
1465 if (exists $keys->{'securityLevel'} && |
|
1466 $l->{'meta'}->{'securityLevel'} ne $keys->{'securityLevel'}) |
|
1467 { |
|
1468 next; |
|
1469 } |
|
1470 if (exists $keys->{'securityName'} && |
|
1471 $l->{'meta'}->{'securityName'} ne $keys->{'securityName'}) |
|
1472 { |
|
1473 next; |
|
1474 } |
|
1475 push @targetParams, $l; |
|
1476 } |
|
1477 } |
|
1478 return @targetParams; |
|
1479 } |
|
1480 |
|
1481 sub process_trapsink |
|
1482 { |
|
1483 my ($sinkLine, $informTag, $trapTag) = @_; |
|
1484 my ($paramName, @paramLines, $community, @result, $secModel, |
|
1485 $MPModel, $notifyType, %profiles, $foundParams); |
|
1486 log_message "Migrating trapsink: ".$sinkLine->{'new'}."\n"; |
|
1487 if ($sinkLine->{'meta'}->{'directive'} eq 'trapsink') { |
|
1488 $secModel = $SECURITY_MODEL_SNMPV1; |
|
1489 $MPModel = $MPMODEL_SNMPV1; |
|
1490 } elsif ($sinkLine->{'meta'}->{'directive'} eq 'trap2sink' || |
|
1491 $sinkLine->{'meta'}->{'directive'} eq 'informsink') { |
|
1492 $secModel = $SECURITY_MODEL_SNMPV2C; |
|
1493 $MPModel = $MPMODEL_SNMPV2C; |
|
1494 } |
|
1495 if ($sinkLine->{'meta'}->{'directive'} eq 'informsink') { |
|
1496 $notifyType = $NOTIFY_TYPE_INFORM; |
|
1497 } else { |
|
1498 $notifyType = $NOTIFY_TYPE_TRAP; |
|
1499 } |
|
1500 $community = $sinkLine->{'meta'}->{'community'}; |
|
1501 |
|
1502 # try to find an existing target param in SMA config but don't bother if we |
|
1503 # don't care about overlap |
|
1504 if ($::EXTEND_SMA_FILTERS) { |
|
1505 @paramLines = (get_targetParams({'securityName'=>$community, |
|
1506 'securityModel'=>$SECURITY_MODEL_SNMPV2C}, \%::SMA_CONFIGS), |
|
1507 get_targetParams({'securityName'=>$community, |
|
1508 'securityModel'=>$SECURITY_MODEL_SNMPV1}, \%::SMA_CONFIGS)); |
|
1509 } |
|
1510 |
|
1511 my ($smaParamLine, $smaTargetLine); |
|
1512 my ($targetName, @targetAddrs); |
|
1513 my ($host) = $sinkLine->{'meta'}->{'host'}; |
|
1514 my ($port) = $sinkLine->{'meta'}->{'port'}; |
|
1515 |
|
1516 if (@paramLines) { |
|
1517 my ($paramLine); |
|
1518 for $paramLine (@paramLines) { |
|
1519 $paramName = $paramLine->{'meta'}->{'paramName'}; |
|
1520 push @targetAddrs, get_targetAddrs({'TDomain'=>$SNMP_UDP_DOMAIN, |
|
1521 'TAddress'=>hostnameToUDPDomain($host.':'.$port), |
|
1522 'paramName'=>$paramName}, \%::SMA_CONFIGS) |
|
1523 } |
|
1524 |
|
1525 # try to use an existing targetAddr if it was defined |
|
1526 if (@targetAddrs > 0) { |
|
1527 $smaTargetLine = $targetAddrs[0]; |
|
1528 ($smaParamLine) = get_targetParams({'paramName'=>$smaTargetLine->{'meta'}->{'paramName'}}, \%::SMA_CONFIGS); |
|
1529 $foundParams = 1; |
|
1530 } |
|
1531 } |
|
1532 |
|
1533 if (! $foundParams || ! $::KEEP_SNMP_TARGET_PARAMS) { |
|
1534 # we need to generate a new set of params |
|
1535 $paramName = get_new_paramName(); |
|
1536 push @result, {'meta'=>{'directive'=>'targetParams', |
|
1537 'paramName'=>$paramName, |
|
1538 'MPModel'=>$MPModel, |
|
1539 'securityModel'=>$secModel, |
|
1540 'securityName'=>$community, |
|
1541 'securityLevel'=>$SECURITY_LEVEL_AUTHNOPRIV, |
|
1542 'storageType'=>$DEFAULT_STORAGE_TYPE, |
|
1543 'rowStatus'=>$DEFAULT_ROW_STATUS} |
|
1544 }; |
|
1545 } |
|
1546 |
|
1547 my (@profiles, $profileName); |
|
1548 |
|
1549 if (! $foundParams) { |
|
1550 # no equivalent SMA target found - only MASF traps to be delivered |
|
1551 # generate our own targetAddr |
|
1552 my ($i) = (0); |
|
1553 $targetName = get_new_targetName($host); |
|
1554 push @result, {'meta'=>{'directive'=>'targetAddr', |
|
1555 'targetName'=>$targetName, |
|
1556 'TDomain'=>$SNMP_UDP_DOMAIN, |
|
1557 'TAddress'=>hostnameToUDPDomain($host.':'.$port), |
|
1558 'timeout'=>1500, |
|
1559 'retryCount'=>3, |
|
1560 'tagList'=>$notifyType == $NOTIFY_TYPE_INFORM ? $informTag : |
|
1561 $trapTag, |
|
1562 'paramName'=>$paramName, |
|
1563 'storageType'=>$DEFAULT_STORAGE_TYPE, |
|
1564 'rowStatus'=>$DEFAULT_ROW_STATUS}}; |
|
1565 # need to add a filter profile |
|
1566 $profileName = get_new_profileName(); |
|
1567 } elsif (! $::KEEP_SNMP_TARGET_PARAMS) { |
|
1568 # we need to change the targetAddr to refer to the new set of params |
|
1569 $targetName = $smaTargetLine->{'meta'}->{'targetName'}; |
|
1570 $smaTargetLine->{'meta'}->{'paramName'} = $paramName; |
|
1571 $smaTargetLine->{'meta'}->{'tagList'} = |
|
1572 ($notifyType == $NOTIFY_TYPE_INFORM ? $informTag : $trapTag); |
|
1573 replace_line(\%::SMA_CONFIGS, $smaTargetLine, $smaTargetLine); |
|
1574 |
|
1575 # set our params to use the new set of filter profiles |
|
1576 @profiles = get_filterProfiles( |
|
1577 {'paramName'=>$smaParamLine->{'meta'}->{'paramName'}}, |
|
1578 \%::SMA_CONFIGS); |
|
1579 if (@profiles > 0) { |
|
1580 $profileName = $profiles[0]->{'meta'}->{'profileName'}; |
|
1581 } else { |
|
1582 # no filter profiles defined |
|
1583 return @result; |
|
1584 } |
|
1585 } else { |
|
1586 # don't change existing target specification |
|
1587 # SMA profiles already have MASF added. |
|
1588 return @result; |
|
1589 } |
|
1590 |
|
1591 push @result, {'meta'=>{'directive'=>'snmpNotifyFilterProfileTable', |
|
1592 'paramName'=>$paramName, |
|
1593 'profileName'=>$profileName, |
|
1594 'storageType'=>$DEFAULT_STORAGE_TYPE, |
|
1595 'rowStatus'=>$DEFAULT_ROW_STATUS} |
|
1596 }; |
|
1597 |
|
1598 if ($foundParams) { |
|
1599 return @result; |
|
1600 } |
|
1601 |
|
1602 # add some filters |
|
1603 push @result, |
|
1604 {'comment'=>'# Include ENTITY-MIB and SUN-PLATFORM-MIB in profile', |
|
1605 'meta'=>{'directive'=>'snmpNotifyFilterTable', |
|
1606 'profileName'=>$profileName, |
|
1607 'subtree'=>$ENTITY_MIB_OID, |
|
1608 'mask'=>'', |
|
1609 'filterType'=>$FILTER_TYPE_INCLUDED, |
|
1610 'storageType'=>$DEFAULT_STORAGE_TYPE, |
|
1611 'rowStatus'=>$DEFAULT_ROW_STATUS |
|
1612 }}, |
|
1613 {'meta'=>{'directive'=>'snmpNotifyFilterTable', |
|
1614 'profileName'=>$profileName, |
|
1615 'subtree'=>$SUNPLAT_MIB_OID, |
|
1616 'mask'=>'', |
|
1617 'filterType'=>$FILTER_TYPE_INCLUDED, |
|
1618 'storageType'=>$DEFAULT_STORAGE_TYPE, |
|
1619 'rowStatus'=>$DEFAULT_ROW_STATUS |
|
1620 }}; |
|
1621 return @result; |
|
1622 } |
|
1623 |
|
1624 sub process_trapsinks |
|
1625 { |
|
1626 # grab all the trapsink, trap2sink and informsink lines in MASF |
|
1627 my (@sinkLines) = (get_lines('trapsink', \%::MASF_CONFIGS), |
|
1628 get_lines('trap2sink', \%::MASF_CONFIGS), |
|
1629 get_lines('informsink', \%::MASF_CONFIGS)); |
|
1630 my ($sinkLine, $paramName, @paramLines, $community, @result, $secModel, |
|
1631 $MPModel, $notifyType, $informTag, $trapTag, %profiles, $foundParams); |
|
1632 %profiles=(); |
|
1633 foreach $sinkLine (@sinkLines) { |
|
1634 $paramName = undef; |
|
1635 @result = (); |
|
1636 $foundParams = 0; |
|
1637 log_message "Processing trapsink: ".$sinkLine->{'new'}."\n"; |
|
1638 if (!defined $informTag) { |
|
1639 $informTag = generate_notify_tags('masfInformTag'); |
|
1640 log_message "Using tag ".$informTag." for informs\n"; |
|
1641 $trapTag = generate_notify_tags('masfTrapTag'); |
|
1642 log_message "Using tag ".$trapTag." for traps\n"; |
|
1643 push @result, {'meta'=>{'directive'=>'snmpNotifyTable', |
|
1644 'notifyName'=>$informTag, |
|
1645 'notifyTag'=>$informTag, |
|
1646 'notifyType'=>$NOTIFY_TYPE_INFORM, |
|
1647 'storageType'=>$DEFAULT_STORAGE_TYPE, |
|
1648 'rowStatus'=>$DEFAULT_ROW_STATUS |
|
1649 }}, |
|
1650 {'meta'=>{'directive'=>'snmpNotifyTable', |
|
1651 'notifyName'=>$trapTag, |
|
1652 'notifyTag'=>$trapTag, |
|
1653 'notifyType'=>$NOTIFY_TYPE_TRAP, |
|
1654 'storageType'=>$DEFAULT_STORAGE_TYPE, |
|
1655 'rowStatus'=>$DEFAULT_ROW_STATUS |
|
1656 }}; |
|
1657 } |
|
1658 push @result, process_trapsink($sinkLine, $informTag, $trapTag); |
|
1659 replace_line(\%::MASF_CONFIGS, $sinkLine, @result); |
|
1660 } |
|
1661 } |
|
1662 |
|
1663 sub extend_sma_trap_filters |
|
1664 { |
|
1665 my (@lines, $line); |
|
1666 @lines = get_lines('snmpNotifyFilterTable', \%::SMA_CONFIGS); |
|
1667 my (%hash); |
|
1668 foreach $line (@lines) { |
|
1669 if (!exists $hash{$line->{'meta'}->{'profileName'}}) { |
|
1670 log_message "Adding ENTITY-MIB and SUN-PLATFORM-MIB traps to ". |
|
1671 "trap filter profile ".$line->{'meta'}->{'profileName'}."\n"; |
|
1672 $hash{$line->{'meta'}->{'profileName'}}=undef; |
|
1673 insert_lines(\%::SMA_CONFIGS, $line, 0, |
|
1674 {'comment'=>'# Include ENTITY-MIB and SUN-PLATFORM-MIB in profile', |
|
1675 'meta'=>{'directive'=>'snmpNotifyFilterTable', |
|
1676 'profileName'=>$line->{'meta'}->{'profileName'}, |
|
1677 'subtree'=>$ENTITY_MIB_OID, |
|
1678 'mask'=>'', |
|
1679 'filterType'=>$FILTER_TYPE_INCLUDED, |
|
1680 'storageType'=>$DEFAULT_STORAGE_TYPE, |
|
1681 'rowStatus'=>$DEFAULT_ROW_STATUS}}, |
|
1682 {'meta'=>{'directive'=>'snmpNotifyFilterTable', |
|
1683 'profileName'=>$line->{'meta'}->{'profileName'}, |
|
1684 'subtree'=>$SUNPLAT_MIB_OID, |
|
1685 'mask'=>'', |
|
1686 'filterType'=>$FILTER_TYPE_INCLUDED, |
|
1687 'storageType'=>$DEFAULT_STORAGE_TYPE, |
|
1688 'rowStatus'=>$DEFAULT_ROW_STATUS}}); |
|
1689 } |
|
1690 } |
|
1691 } |
|
1692 |
|
1693 sub process_trapcommunity |
|
1694 { |
|
1695 my ($configs)=@_; |
|
1696 my ($i, $file, $trapcommunity, $meta); |
|
1697 $trapcommunity = 'public'; |
|
1698 foreach $file (values %$configs) { |
|
1699 for ($i = 0; $i < @$file; $i++) { |
|
1700 $meta = $file->[$i]->{'meta'}; |
|
1701 if (! exists $file->[$i]->{'meta'}->{'directive'}) { |
|
1702 next; |
|
1703 } |
|
1704 if ($meta->{'directive'} eq 'trapcommunity') { |
|
1705 $trapcommunity = $meta->{'community'}; |
|
1706 replace_line($configs, $file->[$i], {'meta'=>{}}); |
|
1707 next; |
|
1708 } |
|
1709 if ($meta->{'directive'} eq 'trapsink' || |
|
1710 $meta->{'directive'} eq 'trap2sink' || |
|
1711 $meta->{'directive'} eq 'informsink') { |
|
1712 if (! exists $meta->{'community'}) { |
|
1713 $meta->{'community'} = $trapcommunity; |
|
1714 replace_line($configs, $file->[$i], $file->[$i]); |
|
1715 } |
|
1716 if (! exists $meta->{'port'}) { |
|
1717 $meta->{'port'} = 162; |
|
1718 replace_line($configs, $file->[$i], $file->[$i]); |
|
1719 } |
|
1720 } |
|
1721 } |
|
1722 } |
|
1723 } |
|
1724 |
|
1725 sub check_duplicate_trap_destinations |
|
1726 { |
|
1727 my (@smaTraps) = (get_lines('informsink', \%::SMA_CONFIGS), |
|
1728 get_lines('trapsink', \%::SMA_CONFIGS), |
|
1729 get_lines('trap2sink', \%::SMA_CONFIGS)); |
|
1730 my (@masfTraps) = (get_lines('informsink', \%::MASF_CONFIGS), |
|
1731 get_lines('trapsink', \%::MASF_CONFIGS), |
|
1732 get_lines('trap2sink', \%::MASF_CONFIGS)); |
|
1733 my ($trap, @matches, $match); |
|
1734 for $trap (@masfTraps) { |
|
1735 @matches = grep ( |
|
1736 ($_->{'meta'}->{'community'} eq $trap->{'meta'}->{'community'} && |
|
1737 $_->{'meta'}->{'host'} eq $trap->{'meta'}->{'host'} && |
|
1738 $_->{'meta'}->{'port'} eq $trap->{'meta'}->{'port'}), @smaTraps); |
|
1739 if (@matches) { |
|
1740 # remove this duplicate |
|
1741 log_message "Removing duplicate ".$trap->{'meta'}->{'directive'}." directive\n", $trap; |
|
1742 replace_line(\%::MASF_CONFIGS, $trap, {'meta'=>{}}); |
|
1743 } |
|
1744 } |
|
1745 } |
|
1746 |
|
1747 ############################################################################## |
|
1748 # Access control, groups and users |
|
1749 |
|
1750 $::SEEDED = 0; |
|
1751 |
|
1752 sub remove_v3_users |
|
1753 { |
|
1754 my (@users) = get_securityNames({'securityModel'=>'usm'}, \%::MASF_CONFIGS); |
|
1755 my ($user, @groups, $group); |
|
1756 for $user (@users) { |
|
1757 replace_line(\%::MASF_CONFIGS, $user, {'meta'=>{}}); |
|
1758 @groups = get_groups($user->{'meta'}, \%::MASF_CONFIGS); |
|
1759 for $group (@groups) { |
|
1760 replace_line(\%::MASF_CONFIGS, $group, {'meta'=>{}}); |
|
1761 } |
|
1762 } |
|
1763 } |
|
1764 |
|
1765 sub remove_v1v2c_users |
|
1766 { |
|
1767 my (@users) = get_securityNames({'securityModel'=>'v1'}, \%::MASF_CONFIGS); |
|
1768 my ($user, @groups, $group); |
|
1769 for $user (@users) { |
|
1770 replace_line(\%::MASF_CONFIGS, $user, {'meta'=>{}}); |
|
1771 @groups = get_groups($user->{'meta'}, \%::MASF_CONFIGS); |
|
1772 for $group (@groups) { |
|
1773 replace_line(\%::MASF_CONFIGS, $group, {'meta'=>{}}); |
|
1774 } |
|
1775 } |
|
1776 } |
|
1777 |
|
1778 sub generate_password |
|
1779 { |
|
1780 my ($i, $r, $pwd); |
|
1781 if (! $::SEEDED) { |
|
1782 srand; |
|
1783 $::SEEDED=1; |
|
1784 } |
|
1785 |
|
1786 for ($i = 0; $i < 8; $i++) { |
|
1787 do { |
|
1788 $r = chr (int (rand 127)); |
|
1789 } while ($r!~/^[a-zA-Z0-9]$/); |
|
1790 $pwd.=$r; |
|
1791 } |
|
1792 return $pwd; |
|
1793 } |
|
1794 |
|
1795 # check to see whether MASF UsmUser directives can be transferred without |
|
1796 # alteration, if not then convert to a template createUser statement |
|
1797 sub process_engineIDs |
|
1798 { |
|
1799 log_message "\n"; |
|
1800 log_message "Checking to see if USM users defined in usmUser directives can be migrated without modification:\n"; |
|
1801 my ($lines, $line, $can_migrate); |
|
1802 $can_migrate = 1; |
|
1803 # check that no v3 users have been specified in SMA |
|
1804 my (@v3_sma_users) = (get_securityNames({'securityModel'=>'usm'}, \%::SMA_CONFIGS)); |
|
1805 if (@v3_sma_users > 0) { |
|
1806 log_message "V3 users were specified in SMA config - cannot migrate without modification.\n"; |
|
1807 $can_migrate = 0; |
|
1808 } |
|
1809 # If the engineID was specified in MASF then we cannot migrate. Remove it |
|
1810 # from the migrated configuration |
|
1811 for $line (get_lines('engineID', \%::MASF_CONFIGS)) { |
|
1812 $can_migrate = 0; |
|
1813 log_message "engineID specified in configuration file - cannot migrate without modification.\n", $line; |
|
1814 replace_line(\%::MASF_CONFIGS, $line, {'meta'=>{}}); |
|
1815 } |
|
1816 # check that engineID isn't specified anywhere in SMA config |
|
1817 for $line (get_lines('engineID', \%::SMA_CONFIGS)) { |
|
1818 log_message "engineID specified in configuration file - cannot migrate without modification.\n", $line; |
|
1819 $can_migrate = 0; |
|
1820 } |
|
1821 |
|
1822 if (! $can_migrate) { |
|
1823 for $line (get_lines('usmUser', \%::MASF_CONFIGS)) { |
|
1824 if (! $::IGNORE_ENGINEID) { |
|
1825 log_message "User with securityName ". |
|
1826 $line->{'meta'}->{'securityName'}." cannot be migrated ". |
|
1827 "because the engineID has changed - aborting.\n", $line; |
|
1828 exit 1; |
|
1829 } |
|
1830 log_message "\n"; |
|
1831 log_message "***************************************************************************\n"; |
|
1832 log_message 'User with securityName '. |
|
1833 $line->{'meta'}->{'securityName'}." has had their password reset.\n"; |
|
1834 log_message "You will need to edit the configuration file after ". |
|
1835 "this script has finished\n". |
|
1836 "in order to enable their account\n"; |
|
1837 log_message "***************************************************************************\n"; |
|
1838 replace_line(\%::MASF_CONFIGS, $line, |
|
1839 {'comment'=>'# XXX Change the password if necessary', |
|
1840 'meta'=>{'directive'=>'createUser', |
|
1841 'securityModel'=>'usm', |
|
1842 'securityName'=>$line->{'meta'}->{'securityName'}, |
|
1843 'authPassword'=>generate_password(), |
|
1844 'authProtocol'=>'MD5'}}); |
|
1845 } |
|
1846 # if we can't migrate the engineID, then remove any oldEngineID |
|
1847 # statements and engineBoots statements |
|
1848 for $line (get_lines('oldEngineID', \%::MASF_CONFIGS), |
|
1849 get_lines('engineBoots', \%::MASF_CONFIGS)) { |
|
1850 replace_line(\%::MASF_CONFIGS, $line, {'meta'=>{}}); |
|
1851 } |
|
1852 return; |
|
1853 } else { |
|
1854 log_message "OK to migrate usm users\n"; |
|
1855 } |
|
1856 |
|
1857 # check to see if oldEngineID or engineBoots is defined in SMA config - if |
|
1858 # so then squash it in favour of new one from MASF |
|
1859 for $line (get_lines('oldEngineID', \%::SMA_CONFIGS), |
|
1860 get_lines('engineBoots', \%::SMA_CONFIGS)) { |
|
1861 replace_line(\%::SMA_CONFIGS, $line, {'meta'=>{}}); |
|
1862 } |
|
1863 } |
|
1864 |
|
1865 # ensure that if a createUser and usmUser directive is present for the same |
|
1866 # securityName then the createUser directive takes precedence |
|
1867 sub check_usm_securityNames |
|
1868 { |
|
1869 my (@masfUserLines)=(get_securityNames({'securityModel'=>'usm'}, |
|
1870 \%::MASF_CONFIGS)); |
|
1871 my (@smaUserLines)=(get_securityNames({'securityModel'=>'usm'}, |
|
1872 \%::SMA_CONFIGS)); |
|
1873 my ($usmUser, $user, $config); |
|
1874 for $config (\%::MASF_CONFIGS, \%::SMA_CONFIGS) { |
|
1875 my (@userLines) = (get_securityNames({'securityModel'=>'usm'}, |
|
1876 $config)); |
|
1877 my (@createUsers) = (grep 'createUser' eq $_->{'meta'}->{'directive'}, @userLines); |
|
1878 for $user (@createUsers) { |
|
1879 my (@usmUsers) = (grep (('usmUser' eq $_->{'meta'}->{'directive'} |
|
1880 && $user->{'meta'}->{'securityName'} eq |
|
1881 $_->{'meta'}->{'securityName'}), @userLines)); |
|
1882 for $usmUser (@usmUsers) { |
|
1883 replace_line($config, $usmUser, {'meta'=>{}}); |
|
1884 } |
|
1885 } |
|
1886 } |
|
1887 } |
|
1888 |
|
1889 sub choose_group_membership |
|
1890 { |
|
1891 my ($smaSecurityName, $masfSecurityName) = @_; |
|
1892 # interactive mode |
|
1893 convert_metadata(); |
|
1894 log_message "\nThis user is defined in SMA with the following configuration:\n"; |
|
1895 # get the config: |
|
1896 my ($o, $n) = get_old_new_config($smaSecurityName, |
|
1897 \%::SMA_CONFIGS); |
|
1898 |
|
1899 log_message "Original configuration:\n".join ("\n",@$o); |
|
1900 log_message "\n\nProposed configuration 1:\n".join ("\n",@$n); |
|
1901 ($o, $n) = get_old_new_config($masfSecurityName, \%::MASF_CONFIGS); |
|
1902 log_message "\n\nIt conflicts with the following MASF configuration:\nOriginal configuration:\n".join ("\n", @$o); |
|
1903 log_message "\n\nProposed configuration 2:\n".join ("\n",@$n)."\n"; |
|
1904 my ($response) = (prompt ("Please choose one of the". |
|
1905 " proposed configurations", 1, [1,2])); |
|
1906 if ($response == 1) { |
|
1907 remove_com2sec_user ({'securityName'=>$masfSecurityName}, \%::MASF_CONFIGS); |
|
1908 } else { |
|
1909 remove_com2sec_user ({'securityName'=>$smaSecurityName}, \%::SMA_CONFIGS); |
|
1910 } |
|
1911 } |
|
1912 |
|
1913 sub process_usm_securityNames |
|
1914 { |
|
1915 my ($file, $line, $fileb, $lineb, $snameLine, $sname, $conflicted); |
|
1916 for $snameLine (get_securityNames({'securityModel'=>'usm'}, \%::MASF_CONFIGS)) { |
|
1917 $sname = $snameLine->{'meta'}->{'securityName'}; |
|
1918 $conflicted = undef; |
|
1919 for $file (values %::SMA_CONFIGS) { |
|
1920 for $line (@$file) { |
|
1921 if (exists $line->{'meta'}->{'securityName'} && |
|
1922 $line->{'meta'}->{'securityName'} eq $sname) { |
|
1923 $conflicted=$line; |
|
1924 last; |
|
1925 } |
|
1926 } |
|
1927 } |
|
1928 if (defined $conflicted) { |
|
1929 # there is a clash |
|
1930 log_message "MASF securityName ".$sname." conflicts with one already defined in SMA\n", $snameLine; |
|
1931 if ($::KEEP_SMA_USM_USERS) { |
|
1932 remove_com2sec_user($snameLine->{'meta'}, \%::MASF_CONFIGS); |
|
1933 } elsif ($::KEEP_MASF_USM_USERS) { |
|
1934 remove_com2sec_user($conflicted->{'meta'}, \%::SMA_CONFIGS); |
|
1935 } elsif ($::AUTOMATED) { |
|
1936 log_message "Conflicting securityNames found - aborting. Please resolve these conflicts\n". |
|
1937 "manually.\n"; |
|
1938 exit 1; |
|
1939 } else { |
|
1940 choose_group_membership($conflicted->{'meta'}->{'securityName'}, $sname); |
|
1941 } |
|
1942 } |
|
1943 } |
|
1944 } |
|
1945 |
|
1946 sub remove_com2sec_user |
|
1947 { |
|
1948 my ($keys, $config)=@_; |
|
1949 my ($securityName)=($keys->{'securityName'}); |
|
1950 my ($f, $l); |
|
1951 for $l (get_securityNames($keys, $config)) { |
|
1952 replace_line ($config, $l, {'meta'=>{}}); |
|
1953 } |
|
1954 for $f (values %$config) { |
|
1955 for $l (@$f) { |
|
1956 if (exists $l->{'meta'}->{'directive'} && |
|
1957 $l->{'meta'}->{'directive'} eq 'group' && |
|
1958 $l->{'meta'}->{'securityName'} eq $securityName) { |
|
1959 replace_line($config, $l, {'meta'=>{}}); |
|
1960 } |
|
1961 } |
|
1962 } |
|
1963 } |
|
1964 |
|
1965 # get all lines which define a security name i.e. com2sec, createUser or |
|
1966 # usmUser, according to specified keys |
|
1967 sub get_securityNames |
|
1968 { |
|
1969 my ($keys, $configs)=@_; |
|
1970 my ($f, $l, @securityNames); |
|
1971 for $f (values %$configs) { |
|
1972 for $l (@$f) { |
|
1973 if (! exists $l->{'meta'}->{'directive'} || |
|
1974 ($l->{'meta'}->{'directive'} ne 'createUser' && |
|
1975 $l->{'meta'}->{'directive'} ne 'usmUser' && |
|
1976 $l->{'meta'}->{'directive'} ne 'com2sec')) { |
|
1977 next; |
|
1978 } |
|
1979 if (exists $keys->{'securityName'} && |
|
1980 $l->{'meta'}->{'securityName'} ne $keys->{'securityName'}) { |
|
1981 next; |
|
1982 } |
|
1983 if (exists $keys->{'securityModel'}) { |
|
1984 my ($sm) = ('usm'); |
|
1985 if ($keys->{'securityModel'} eq 'v2c' || |
|
1986 $keys->{'securityModel'} eq 'v1') { |
|
1987 $sm = 'v1'; |
|
1988 } |
|
1989 if (($sm eq 'v1' && |
|
1990 $l->{'meta'}->{'directive'} ne 'com2sec') || |
|
1991 ($sm eq 'usm' && |
|
1992 ($l->{'meta'}->{'directive'} ne 'createUser' && |
|
1993 $l->{'meta'}->{'directive'} ne 'usmUser'))) { |
|
1994 next; |
|
1995 } |
|
1996 } |
|
1997 push @securityNames, $l; |
|
1998 } |
|
1999 } |
|
2000 return @securityNames; |
|
2001 } |
|
2002 |
|
2003 sub get_groups |
|
2004 { |
|
2005 my ($keys, $configs)=@_; |
|
2006 my ($f, $l, @groups); |
|
2007 for $f (values %$configs) { |
|
2008 for $l (@$f) { |
|
2009 if (! exists $l->{'meta'}->{'directive'} || |
|
2010 $l->{'meta'}->{'directive'} ne 'group') { |
|
2011 next; |
|
2012 } |
|
2013 if (exists $keys->{'securityName'} && |
|
2014 $l->{'meta'}->{'securityName'} ne $keys->{'securityName'}) { |
|
2015 next; |
|
2016 } |
|
2017 if (exists $keys->{'securityModel'} && |
|
2018 $l->{'meta'}->{'securityModel'} ne $keys->{'securityModel'}) { |
|
2019 next; |
|
2020 } |
|
2021 if (exists $keys->{'groupName'} && |
|
2022 $l->{'meta'}->{'groupName'} ne $keys->{'groupName'}) { |
|
2023 next; |
|
2024 } |
|
2025 push @groups, $l |
|
2026 } |
|
2027 } |
|
2028 return @groups; |
|
2029 } |
|
2030 |
|
2031 sub get_access { |
|
2032 my ($keys, $configs)=@_; |
|
2033 my ($f, $l, @access); |
|
2034 for $f (values %$configs) { |
|
2035 for $l (@$f) { |
|
2036 if (! exists $l->{'meta'}->{'directive'} || |
|
2037 $l->{'meta'}->{'directive'} ne 'access') { |
|
2038 next; |
|
2039 } |
|
2040 if (exists $keys->{'groupName'} && |
|
2041 $l->{'meta'}->{'groupName'} ne $keys->{'groupName'}) { |
|
2042 next; |
|
2043 } |
|
2044 if (exists $keys->{'viewName'} && |
|
2045 ($l->{'meta'}->{'readView'} ne $keys->{'viewName'} && |
|
2046 $l->{'meta'}->{'writeView'} ne $keys->{'viewName'} && |
|
2047 $l->{'meta'}->{'notifyView'} ne $keys->{'viewName'})) { |
|
2048 next; |
|
2049 } |
|
2050 push @access, $l |
|
2051 } |
|
2052 } |
|
2053 return @access; |
|
2054 } |
|
2055 |
|
2056 sub get_views { |
|
2057 my ($keys, $configs)=@_; |
|
2058 my ($f, $l, @views); |
|
2059 if (exists $keys->{'viewName'} && |
|
2060 $keys->{'viewName'} eq '') { |
|
2061 return (); |
|
2062 } |
|
2063 for $f (values %$configs) { |
|
2064 for $l (@$f) { |
|
2065 if (! exists $l->{'meta'}->{'directive'} || |
|
2066 $l->{'meta'}->{'directive'} ne 'view') { |
|
2067 next; |
|
2068 } |
|
2069 if (exists $keys->{'viewName'} && |
|
2070 $l->{'meta'}->{'viewName'} ne $keys->{'viewName'}) { |
|
2071 next; |
|
2072 } |
|
2073 push @views, $l |
|
2074 } |
|
2075 } |
|
2076 return @views; |
|
2077 } |
|
2078 |
|
2079 sub get_old_new_config |
|
2080 { |
|
2081 my ($securityName, $configs) = @_; |
|
2082 my ($line, @secNames, @groups, $group, $access, @accesses, @views, @old, @new); |
|
2083 my (@a, $keys); |
|
2084 $keys = {'securityName'=>$securityName}; |
|
2085 @secNames = get_securityNames($keys, $configs); |
|
2086 @groups = get_groups ({'securityName'=>$securityName}, $configs); |
|
2087 # get other members of this group |
|
2088 if (@groups > 0) { |
|
2089 @groups = set_union([get_groups({'groupName'=>$groups[0]->{'meta'}->{'groupName'}}, $configs)], \@groups); |
|
2090 } |
|
2091 for $group (@groups) { |
|
2092 (@accesses) = (set_union(\@accesses, [get_access($group->{'meta'}, $configs)])); |
|
2093 } |
|
2094 for $access (@accesses) { |
|
2095 $keys = {'viewName'=>$access->{'meta'}->{'readView'}}; |
|
2096 (@views) = (set_union(\@views, [get_views($keys, $configs)])); |
|
2097 $keys->{'viewName'}=$access->{'meta'}->{'writeView'}; |
|
2098 (@views) = (set_union(\@views, [get_views($keys, $configs)])); |
|
2099 $keys->{'viewName'}=$access->{'meta'}->{'notifyView'}; |
|
2100 (@views) = (set_union(\@views, [get_views($keys, $configs)])); |
|
2101 } |
|
2102 for $line (@secNames, @groups, @accesses, @views) { |
|
2103 if (exists $line->{'orig'}) { |
|
2104 push @old, $line->{'orig'}; |
|
2105 } |
|
2106 if (exists $line->{'new'}) { |
|
2107 push @new, $line->{'new'}; |
|
2108 } |
|
2109 } |
|
2110 return [@old], [@new]; |
|
2111 } |
|
2112 |
|
2113 sub parse_source |
|
2114 { |
|
2115 my ($line) = @_; |
|
2116 my ($source) = $line->{'meta'}->{'source'}; |
|
2117 my ($hostIP, $mask, $ipSegment); |
|
2118 # was it 'default' |
|
2119 if ($source eq 'default' || $source eq '0.0.0.0') { |
|
2120 return (inet_aton('0.0.0.0'), inet_aton('0.0.0.0')); |
|
2121 } |
|
2122 # try to resolve as a plain IP address or a hostname |
|
2123 $ipSegment=$source; |
|
2124 ($ipSegment, $mask) = split /\//, $source; |
|
2125 # try to resolve hostname as an IP address |
|
2126 my ($hostent) = gethostbyname($ipSegment); |
|
2127 if (defined $hostent) { |
|
2128 if ($hostent->addrtype ne AF_INET) { |
|
2129 log_message "Unsupported address family in source $source\n", $line; |
|
2130 exit 1; |
|
2131 } |
|
2132 my (@hostIPs) = @{$hostent->addr_list}; |
|
2133 log_message "resolved $source to ".inet_ntoa($hostIPs[0])."\n", $line; |
|
2134 $hostIP = $hostIPs[0]; |
|
2135 } else { |
|
2136 log_message "Couldn't resolve $ipSegment as a hostname or IP address\n", $line; |
|
2137 exit 1; |
|
2138 } |
|
2139 # try to resolve as subnet/mask |
|
2140 if (defined $mask && $mask ne '') { |
|
2141 my $netmask; |
|
2142 $netmask = inet_aton($mask); |
|
2143 if (! defined $netmask) { |
|
2144 |
|
2145 # try to interpret as number between 0 and 32 |
|
2146 my ($bit) = (0x80000000); |
|
2147 $netmask = 0; |
|
2148 if ($mask < 0 || $mask > 32) { |
|
2149 log_message "$source did not contain a valid netmask.\n", $line; |
|
2150 exit 1; |
|
2151 } |
|
2152 while ($mask > 0) { |
|
2153 $netmask |= $bit; |
|
2154 $bit = $bit >> 1; |
|
2155 } |
|
2156 } |
|
2157 my ($N, $H) = (in_addr_to_number ($netmask), in_addr_to_number |
|
2158 ($hostIP)); |
|
2159 if ($H & ~$N) { |
|
2160 log_message("source/mask mismatch - ".inet_ntoa($hostIP).'/'.inet_ntoa($netmask)."\n", $line); |
|
2161 exit 1; |
|
2162 } |
|
2163 return ($hostIP, $netmask); |
|
2164 } else { |
|
2165 # no netmask specified - exact match |
|
2166 return ($hostIP, inet_aton('255.255.255.255')); |
|
2167 } |
|
2168 } |
|
2169 |
|
2170 sub source_overlap |
|
2171 { |
|
2172 my ($linea, $lineb) = @_; |
|
2173 my ($ipa, $maska) = parse_source($linea); |
|
2174 my ($ipb, $maskb) = parse_source($lineb); |
|
2175 my $mask_overlap; |
|
2176 $ipa = in_addr_to_number($ipa); |
|
2177 $ipb = in_addr_to_number($ipb); |
|
2178 $mask_overlap = in_addr_to_number($maska) & in_addr_to_number($maskb); |
|
2179 my $complement = 0xffffffff & (~$mask_overlap); |
|
2180 if (($ipa & $mask_overlap | $complement) == ($ipb & $mask_overlap | $complement)) { |
|
2181 return 1; |
|
2182 } |
|
2183 return 0; |
|
2184 } |
|
2185 |
|
2186 sub community_conflicts |
|
2187 { |
|
2188 my ($linea)=@_; |
|
2189 my ($community, $source) = ($linea->{'meta'}->{'community'}, $linea->{'meta'}->{'source'}); |
|
2190 my ($lines, $line); |
|
2191 for $lines (values %::SMA_CONFIGS) { |
|
2192 for $line (@$lines) { |
|
2193 if (! exists $line->{'meta'}->{'community'} || |
|
2194 $line->{'meta'}->{'community'} ne $community) { |
|
2195 next; |
|
2196 } |
|
2197 if (! exists $line->{'meta'}->{'source'}) { |
|
2198 next; |
|
2199 } |
|
2200 if (source_overlap ($line, $linea)) { |
|
2201 return ($line); |
|
2202 } |
|
2203 } |
|
2204 } |
|
2205 return undef; |
|
2206 } |
|
2207 |
|
2208 sub process_com2sec |
|
2209 { |
|
2210 my ($lines, $line); |
|
2211 my $conflict; |
|
2212 for $lines (values %::MASF_CONFIGS) { |
|
2213 for $line (@$lines) { |
|
2214 if (! exists $line->{'meta'}->{'directive'} || |
|
2215 $line->{'meta'}->{'directive'} ne 'com2sec') { |
|
2216 next; |
|
2217 } |
|
2218 |
|
2219 $conflict = community_conflicts($line); |
|
2220 if (defined $conflict) { |
|
2221 log_message "MASF source ".$line->{'meta'}->{'source'}. |
|
2222 " conflicts with SMA source ".$conflict->{'meta'}->{'source'}. |
|
2223 " defined for community ".$line->{'meta'}->{'community'}."\n", $line; |
|
2224 if ($::KEEP_SMA_GROUPS) { |
|
2225 # remove user from MASF config |
|
2226 remove_com2sec_user ($line->{'meta'}, \%::MASF_CONFIGS); |
|
2227 } elsif ($::KEEP_MASF_GROUPS) { |
|
2228 # remove user from SMA config |
|
2229 remove_com2sec_user ($line->{'meta'}, \%::SMA_CONFIGS); |
|
2230 } elsif ($::AUTOMATED) { |
|
2231 # didn't define what to do so stop! |
|
2232 log_message "Conflicting source/communities found - ". |
|
2233 "aborting. Please resolve these conflicts manually.\n"; |
|
2234 exit 1; |
|
2235 } else { |
|
2236 choose_group_membership($conflict->{'meta'}->{'securityName'}, $line->{'meta'}->{'securityName'}); |
|
2237 } |
|
2238 } |
|
2239 } |
|
2240 } |
|
2241 } |
|
2242 |
|
2243 sub uniquify_viewNames |
|
2244 { |
|
2245 my ($prefix) = @_; |
|
2246 my %mappings=(); |
|
2247 my ($lines, $line, $securityName, $i, @keys, $key, $from); |
|
2248 @keys = ('viewName', 'readView', 'writeView', 'notifyView'); |
|
2249 for $lines (values %::MASF_CONFIGS) { |
|
2250 foreach $line (@$lines) { |
|
2251 for $key (@keys) { |
|
2252 if (exists $line->{'meta'}->{$key} && |
|
2253 $line->{'meta'}->{$key} ne '') { |
|
2254 $from = $line->{'meta'}->{$key}; |
|
2255 } else { |
|
2256 next; |
|
2257 } |
|
2258 |
|
2259 # is there already a mapping for this securityName ? |
|
2260 if (exists $mappings{$from}) { |
|
2261 $line->{'meta'}->{$key} = $mappings{$from}; |
|
2262 replace_line(\%::MASF_CONFIGS, $line, $line); |
|
2263 next; |
|
2264 } |
|
2265 |
|
2266 # generate a new securityName |
|
2267 $i = 0; |
|
2268 while (viewName_exists($prefix.$i.$from)) |
|
2269 { |
|
2270 $i++; |
|
2271 } |
|
2272 if (length $prefix.$i.$from > 32) { |
|
2273 log_message ("Couldn't render viewName $from unique\n", $line); |
|
2274 exit 1; |
|
2275 } |
|
2276 $mappings{$from}=$prefix.$i.$from; |
|
2277 $line->{'meta'}->{$key} = $prefix.$i.$from; |
|
2278 replace_line(\%::MASF_CONFIGS, $line, $line); |
|
2279 } |
|
2280 } |
|
2281 } |
|
2282 # remove redundant view names |
|
2283 my (@viewLines, @accessLines, $view, $config); |
|
2284 for $config (\%::MASF_CONFIGS, \%::SMA_CONFIGS) { |
|
2285 @viewLines = get_views({}, $config); |
|
2286 for $view (@viewLines) { |
|
2287 @accessLines = (get_access($view->{'meta'}, \%::MASF_CONFIGS), get_access($view->{'meta'}, \%::SMA_CONFIGS)); |
|
2288 if (@accessLines == 0) { |
|
2289 replace_line($config, $view, {'meta'=>{}}); |
|
2290 } |
|
2291 } |
|
2292 } |
|
2293 } |
|
2294 |
|
2295 sub uniquify_groupNames |
|
2296 { |
|
2297 my ($prefix) = @_; |
|
2298 my %mappings=(); |
|
2299 my ($lines, $line, $securityName, $i, $from); |
|
2300 for $lines (values %::MASF_CONFIGS) { |
|
2301 foreach $line (@$lines) { |
|
2302 if (exists $line->{'meta'}->{'groupName'}) { |
|
2303 $from = $line->{'meta'}->{'groupName'}; |
|
2304 } else { |
|
2305 next; |
|
2306 } |
|
2307 |
|
2308 # is there already a mapping for this securityName ? |
|
2309 if (exists $mappings{$from}) { |
|
2310 $line->{'meta'}->{'groupName'} = $mappings{$from}; |
|
2311 replace_line(\%::MASF_CONFIGS, $line, $line); |
|
2312 next; |
|
2313 } |
|
2314 |
|
2315 # generate a new securityName |
|
2316 $i = 0; |
|
2317 while (groupName_exists($prefix.$i.$from)) |
|
2318 { |
|
2319 $i++; |
|
2320 } |
|
2321 if (length $prefix.$i.$from > 32) { |
|
2322 log_message ("Couldn't render groupName $from unique\n", $line); |
|
2323 exit 1; |
|
2324 } |
|
2325 $mappings{$from}=$prefix.$i.$from; |
|
2326 $line->{'meta'}->{'groupName'} = $prefix.$i.$from; |
|
2327 replace_line(\%::MASF_CONFIGS, $line, $line); |
|
2328 } |
|
2329 } |
|
2330 } |
|
2331 |
|
2332 # remove group directives referring to undefined users |
|
2333 sub clean_group_membership |
|
2334 { |
|
2335 my ($config); |
|
2336 for $config (\%::MASF_CONFIGS, \%::SMA_CONFIGS) { |
|
2337 my (@groups) = get_lines('group', $config); |
|
2338 my ($group); |
|
2339 for $group (@groups) { |
|
2340 my (@securityNames) = get_securityNames($group->{'meta'}, $config); |
|
2341 if (@securityNames == 0) { |
|
2342 # no securityName was defined for this directive - remove the |
|
2343 # directive |
|
2344 log_message "Removing undefined user ". |
|
2345 $group->{'meta'}->{'securityName'}." from group ". |
|
2346 $group->{'meta'}->{'groupName'}."\n", $group; |
|
2347 replace_line($config, $group, {'meta'=>{}}); |
|
2348 } |
|
2349 } |
|
2350 } |
|
2351 } |
|
2352 |
|
2353 sub uniquify_securityNames |
|
2354 { |
|
2355 my ($prefix) = @_; |
|
2356 my ($to); |
|
2357 my ($lines, $line, $securityName, $i, $from, $fromLine); |
|
2358 for $fromLine (get_securityNames({'securityModel'=>'v1'}, |
|
2359 \%::MASF_CONFIGS)) { |
|
2360 # generate a new securityName |
|
2361 $from = $fromLine->{'meta'}->{'securityName'}; |
|
2362 $to = get_new_securityName($prefix.$from); |
|
2363 for $lines (values %::MASF_CONFIGS) { |
|
2364 foreach $line (@$lines) { |
|
2365 if (! exists $line->{'meta'}->{'securityName'} || |
|
2366 $line->{'meta'}->{'securityName'} ne $from) { |
|
2367 next; |
|
2368 } |
|
2369 |
|
2370 $line->{'meta'}->{'securityName'} = $to; |
|
2371 replace_line(\%::MASF_CONFIGS, $line, $line); |
|
2372 } |
|
2373 } |
|
2374 } |
|
2375 } |
|
2376 |
|
2377 sub check_tokens |
|
2378 { |
|
2379 my ($line, $minTokens, $maxTokens, @tokens) = @_; |
|
2380 my ($directive) = $line->{'meta'}->{'directive'}; |
|
2381 if (@tokens < $minTokens || @tokens > $maxTokens) { |
|
2382 log_message "Invalid number of parameters for $directive directive ". |
|
2383 "- Aborting\n", $line; |
|
2384 exit 1; |
|
2385 } |
|
2386 } |
|
2387 |
|
2388 # convert simple array of lines into hash containing data which is what we |
|
2389 # subsequently modify |
|
2390 sub add_metadata |
|
2391 { |
|
2392 my ($lines, $file, $line, $i, $s, $directive, @tokens); |
|
2393 my ($key, $j); |
|
2394 for $key (keys %::SMA_CONFIGS) { |
|
2395 for ($i = 0; $i < @{$::SMA_CONFIGS{$key}}; $i++) { |
|
2396 $line = $::SMA_CONFIGS{$key}->[$i]; |
|
2397 $::SMA_CONFIGS{$key}->[$i] = {'orig'=>$line, |
|
2398 'new'=>$line, |
|
2399 # NB the 'meta' hash doesn't contain metadata, only real data... |
|
2400 'meta'=>{}, |
|
2401 'lineno'=>$i, |
|
2402 'file'=>$key}; |
|
2403 } |
|
2404 } |
|
2405 for $key (keys %::MASF_CONFIGS) { |
|
2406 for ($i = 0; $i < @{$::MASF_CONFIGS{$key}}; $i++) { |
|
2407 $line = $::MASF_CONFIGS{$key}->[$i]; |
|
2408 $::MASF_CONFIGS{$key}->[$i] = {'orig'=>$line, |
|
2409 'new'=>$line, |
|
2410 'meta'=>{}, |
|
2411 'lineno'=>$i, |
|
2412 'file'=>$key}; |
|
2413 } |
|
2414 } |
|
2415 for $lines (values %::SMA_CONFIGS, values %::MASF_CONFIGS) { |
|
2416 for $line (@$lines) { |
|
2417 ($directive, @tokens) = parse_config_line($line->{'new'}); |
|
2418 if ($directive ne '') { |
|
2419 $line->{'meta'}->{'directive'} = $directive; |
|
2420 } |
|
2421 if ($directive eq 'com2sec') { |
|
2422 check_tokens($line, 3, 3, @tokens); |
|
2423 $line->{'meta'}->{'securityName'} = $tokens[0]; |
|
2424 $line->{'meta'}->{'source'} = $tokens[1]; |
|
2425 $line->{'meta'}->{'community'} = $tokens[2]; |
|
2426 } elsif ($directive eq 'group') { |
|
2427 check_tokens($line, 3, 3, @tokens); |
|
2428 $line->{'meta'}->{'groupName'} = $tokens[0]; |
|
2429 $line->{'meta'}->{'securityModel'} = $tokens[1]; |
|
2430 $line->{'meta'}->{'securityName'} = $tokens[2]; |
|
2431 } elsif ($directive eq 'rouser' || $directive eq 'rwuser') { |
|
2432 check_tokens($line, 1, 3, @tokens); |
|
2433 $line->{'meta'}->{'securityName'} = $tokens[0]; |
|
2434 if (defined $tokens[1]) { |
|
2435 $line->{'meta'}->{'securityLevel'} = $tokens[1]; |
|
2436 } |
|
2437 if (defined $tokens[2]) { |
|
2438 $line->{'meta'}->{'oid'} = $tokens[2]; |
|
2439 } |
|
2440 } elsif ($directive eq 'createUser') { |
|
2441 check_tokens($line, 3, 5, @tokens); |
|
2442 $line->{'meta'}->{'securityName'} = $tokens[0]; |
|
2443 $line->{'meta'}->{'authProtocol'} = $tokens[1]; |
|
2444 $line->{'meta'}->{'authPassword'} = $tokens[2]; |
|
2445 $line->{'meta'}->{'securityModel'} = 'usm'; |
|
2446 if (defined $tokens[3]) { |
|
2447 $line->{'meta'}->{'privProtocol'} = $tokens[3]; |
|
2448 } |
|
2449 if (defined $tokens[4]) { |
|
2450 $line->{'meta'}->{'privPassword'} = $tokens[4]; |
|
2451 } |
|
2452 } elsif ($directive eq 'usmUser') { |
|
2453 check_tokens($line, 11, 11, @tokens); |
|
2454 $line->{'meta'}->{'securityName'} = securityName_from_usmUser($directive, @tokens); |
|
2455 $line->{'meta'}->{'securityModel'} = 'usm'; |
|
2456 } elsif ($directive eq 'access') { |
|
2457 check_tokens($line, 8, 8, @tokens); |
|
2458 $line->{'meta'}->{'groupName'} = $tokens[0]; |
|
2459 $line->{'meta'}->{'contextPrefix'} = $tokens[1]; |
|
2460 $line->{'meta'}->{'securityModel'} = $tokens[2]; |
|
2461 $line->{'meta'}->{'securityLevel'} = $tokens[3]; |
|
2462 $line->{'meta'}->{'contextMatch'} = $tokens[4]; |
|
2463 $line->{'meta'}->{'readView'} = $tokens[5]; |
|
2464 $line->{'meta'}->{'writeView'} = $tokens[6]; |
|
2465 $line->{'meta'}->{'notifyView'} = $tokens[7]; |
|
2466 } elsif ($directive eq 'view') { |
|
2467 check_tokens($line, 3, 4, @tokens); |
|
2468 $line->{'meta'}->{'viewName'} = $tokens[0]; |
|
2469 $line->{'meta'}->{'viewType'} = $tokens[1]; |
|
2470 $line->{'meta'}->{'oid'} = $tokens[2]; |
|
2471 if (defined $tokens[3]) { |
|
2472 $line->{'meta'}->{'mask'} = $tokens[3]; |
|
2473 } |
|
2474 } elsif ($directive eq 'rocommunity' || $directive eq 'rwcommunity') { |
|
2475 check_tokens($line, 1, 3, @tokens); |
|
2476 $line->{'meta'}->{'community'} = $tokens[0]; |
|
2477 if (defined $tokens[1]) { |
|
2478 $line->{'meta'}->{'source'} = $tokens[1]; |
|
2479 } else { |
|
2480 $line->{'meta'}->{'source'} = "0.0.0.0/0.0.0.0"; |
|
2481 } |
|
2482 if (defined $tokens[2]) { |
|
2483 $line->{'meta'}->{'oid'} = $tokens[2]; |
|
2484 } |
|
2485 } elsif ($directive eq 'trapcommunity') { |
|
2486 check_tokens($line, 1, 1, @tokens); |
|
2487 $line->{'meta'}->{'community'} = $tokens[0]; |
|
2488 } elsif ($directive eq 'trapsink' || |
|
2489 $directive eq 'trap2sink' || |
|
2490 $directive eq 'informsink') { |
|
2491 check_tokens($line, 1, 3, @tokens); |
|
2492 $line->{'meta'}->{'host'} = $tokens[0]; |
|
2493 if (defined $tokens[1]) { |
|
2494 $line->{'meta'}->{'community'} = $tokens[1]; |
|
2495 } |
|
2496 if (defined $tokens[2]) { |
|
2497 $line->{'meta'}->{'port'} = $tokens[2]; |
|
2498 } |
|
2499 } elsif ($directive eq 'snmpNotifyFilterTable') { |
|
2500 check_tokens($line, 6, 6, @tokens); |
|
2501 $line->{'meta'}->{'profileName'} = $tokens[0]; |
|
2502 $line->{'meta'}->{'subtree'} = $tokens[1]; |
|
2503 $line->{'meta'}->{'mask'} = $tokens[2]; |
|
2504 $line->{'meta'}->{'filterType'} = $tokens[3]; |
|
2505 $line->{'meta'}->{'storageType'} = $tokens[4]; |
|
2506 $line->{'meta'}->{'rowStatus'} = $tokens[5]; |
|
2507 } elsif ($directive eq 'targetParams') { |
|
2508 check_tokens($line, 7, 7, @tokens); |
|
2509 $line->{'meta'}->{'paramName'} = $tokens[0]; |
|
2510 $line->{'meta'}->{'MPModel'} = $tokens[1]; |
|
2511 $line->{'meta'}->{'securityModel'} = $tokens[2]; |
|
2512 $line->{'meta'}->{'securityName'} = $tokens[3]; |
|
2513 $line->{'meta'}->{'securityLevel'} = $tokens[4]; |
|
2514 $line->{'meta'}->{'storageType'} = $tokens[5]; |
|
2515 $line->{'meta'}->{'rowStatus'} = $tokens[6]; |
|
2516 } elsif ($directive eq 'targetAddr') { |
|
2517 check_tokens($line, 9, 9, @tokens); |
|
2518 $line->{'meta'}->{'targetName'} = $tokens[0]; |
|
2519 $line->{'meta'}->{'TDomain'} = $tokens[1]; |
|
2520 $line->{'meta'}->{'TAddress'} = $tokens[2]; |
|
2521 $line->{'meta'}->{'timeout'} = $tokens[3]; |
|
2522 $line->{'meta'}->{'retryCount'} = $tokens[4]; |
|
2523 $line->{'meta'}->{'tagList'} = $tokens[5]; |
|
2524 $line->{'meta'}->{'paramName'} = $tokens[6]; |
|
2525 $line->{'meta'}->{'storageType'} = $tokens[7]; |
|
2526 $line->{'meta'}->{'rowStatus'} = $tokens[8]; |
|
2527 } elsif ($directive eq 'snmpNotifyTable') { |
|
2528 check_tokens($line, 5, 5, @tokens); |
|
2529 $line->{'meta'}->{'notifyName'} = $tokens[0]; |
|
2530 $line->{'meta'}->{'notifyTag'} = $tokens[1]; |
|
2531 $line->{'meta'}->{'notifyType'} = $tokens[2]; |
|
2532 $line->{'meta'}->{'storageType'} = $tokens[3]; |
|
2533 $line->{'meta'}->{'rowStatus'} = $tokens[4]; |
|
2534 } elsif ($directive eq 'snmpNotifyFilterProfileTable') { |
|
2535 check_tokens($line, 4, 4, @tokens); |
|
2536 $line->{'meta'}->{'paramName'} = $tokens[0]; |
|
2537 $line->{'meta'}->{'profileName'} = $tokens[1]; |
|
2538 $line->{'meta'}->{'storageType'} = $tokens[2]; |
|
2539 $line->{'meta'}->{'rowStatus'} = $tokens[3]; |
|
2540 } elsif ($directive eq 'master') { |
|
2541 check_tokens($line, 1, 1, @tokens); |
|
2542 $line->{'meta'}->{'masterMode'} = $tokens[0]; |
|
2543 } elsif ($directive eq 'agentxTimeout') { |
|
2544 check_tokens($line, 1, 1, @tokens); |
|
2545 $line->{'meta'}->{'agentxTimeout'} = $tokens[0]; |
|
2546 } elsif ($directive eq 'agentxRetries') { |
|
2547 check_tokens($line, 1, 1, @tokens); |
|
2548 $line->{'meta'}->{'agentxRetries'} = $tokens[0]; |
|
2549 } |
|
2550 } |
|
2551 } |
|
2552 } |
|
2553 |
|
2554 sub convert_metadata |
|
2555 { |
|
2556 my ($line, $file, $meta, $directive); |
|
2557 my %mps = ($MPMODEL_SNMPV1=>'v1', |
|
2558 $MPMODEL_SNMPV2C=>'v2c', |
|
2559 $MPMODEL_SNMPV2U=>'v2u', |
|
2560 $MPMODEL_SNMPV3=>'v3'); |
|
2561 my %sms = ($SECURITY_MODEL_ANY=>'any', |
|
2562 $SECURITY_MODEL_SNMPV1=>'v1', |
|
2563 $SECURITY_MODEL_SNMPV2C=>'v2c', |
|
2564 $SECURITY_MODEL_USM=>'usm'); |
|
2565 my %sls = ($SECURITY_LEVEL_NOAUTHNOPRIV=>'noAuthNoPriv', |
|
2566 $SECURITY_LEVEL_AUTHNOPRIV=>'authNoPriv', |
|
2567 $SECURITY_LEVEL_AUTHPRIV=>'authPriv'); |
|
2568 my %nts = ($NOTIFY_TYPE_TRAP=>'trap', |
|
2569 $NOTIFY_TYPE_INFORM=>'inform'); |
|
2570 for $file (values %::ADDED_CONFIGS, values %::MASF_CONFIGS, values |
|
2571 %::SMA_CONFIGS) { |
|
2572 for $line (@$file) { |
|
2573 $meta = $line->{'meta'}; |
|
2574 if (exists $meta->{'directive'} && |
|
2575 exists $line->{'changed'}) { |
|
2576 delete $line->{'changed'}; |
|
2577 $directive = $meta->{'directive'}; |
|
2578 if ($directive eq 'com2sec') { |
|
2579 # don't quote securityName or community |
|
2580 $line->{'new'} = "com2sec ".$meta->{'securityName'}. |
|
2581 ' '.$meta->{'source'}.' '.$meta->{'community'}; |
|
2582 } elsif ($directive eq 'group') { |
|
2583 # don't quote groupName |
|
2584 $line->{'new'} = 'group '.$meta->{'groupName'}. |
|
2585 ' '.$meta->{'securityModel'}.' '. |
|
2586 # don't quote securityName |
|
2587 $meta->{'securityName'}.''; |
|
2588 } elsif ($directive eq 'access') { |
|
2589 my ($readView, $writeView, $notifyView) = |
|
2590 map { $_ eq '' ? 'none' : $_ } |
|
2591 ($meta->{'readView'}, $meta->{'writeView'}, |
|
2592 $meta->{'notifyView'}); |
|
2593 # don't quote groupName, or viewNames |
|
2594 $line->{'new'} = 'access '.$meta->{'groupName'}. |
|
2595 ' "'.$meta->{'contextPrefix'}.'" '. |
|
2596 $meta->{'securityModel'}.' '.$meta->{'securityLevel'}. |
|
2597 ' '.$meta->{'contextMatch'}.' '.$readView. |
|
2598 ' '.$writeView.' '.$notifyView; |
|
2599 } elsif ($directive eq 'view') { |
|
2600 # don't quote viewName |
|
2601 $line->{'new'} = 'view '.$meta->{'viewName'}.' '. |
|
2602 $meta->{'viewType'}.' '.$meta->{'oid'}; |
|
2603 if (exists $meta->{'mask'}) { |
|
2604 $line->{'new'}.=' '.$meta->{'mask'}; |
|
2605 } |
|
2606 } elsif ($directive eq 'createUser') { |
|
2607 $line->{'new'} = 'createUser "'.$meta->{'securityName'}. |
|
2608 '" '.$meta->{'authProtocol'}.' "'.$meta->{'authPassword'}. |
|
2609 '"'; |
|
2610 if (exists $meta->{'privProtocol'}) { |
|
2611 $line->{'new'}.=' '.$meta->{'privProtocol'}; |
|
2612 } |
|
2613 if (exists $meta->{'privPassword'}) { |
|
2614 $line->{'new'}.=' "'.$meta->{'privPassword'}.'" '; |
|
2615 } |
|
2616 } elsif ($directive eq 'trap2sink' || |
|
2617 $directive eq 'trapsink' || |
|
2618 $directive eq 'informsink') { |
|
2619 $line->{'new'} = $directive.' '.$meta->{'host'}; |
|
2620 if (exists $meta->{'community'}) { |
|
2621 # don't quote community |
|
2622 $line->{'new'}.=' '.$meta->{'community'}.''; |
|
2623 } |
|
2624 if (exists $meta->{'port'}) { |
|
2625 $line->{'new'}.=' '.$meta->{'port'}; |
|
2626 } |
|
2627 } elsif ($directive eq 'snmpNotifyFilterTable') { |
|
2628 $line->{'new'} = 'snmpNotifyFilterTable "'. |
|
2629 $meta->{'profileName'}.'" '.$meta->{'subtree'}.' "'. |
|
2630 $meta->{'mask'}.'" '.$meta->{'filterType'}.' '. |
|
2631 $meta->{'storageType'}.' '.$meta->{'rowStatus'}; |
|
2632 } elsif ($directive eq 'targetParams') { |
|
2633 $line->{'comment'} = '# targetParams '.$meta->{'paramName'}. |
|
2634 ' '.$mps{$meta->{'MPModel'}}.' '. |
|
2635 $sms{$meta->{'securityModel'}}.' '.$meta->{'securityName'}. |
|
2636 ' '.$sls{$meta->{'securityLevel'}}; |
|
2637 $line->{'new'} = 'targetParams "'.$meta->{'paramName'}.'" '. |
|
2638 $meta->{'MPModel'}.' '.$meta->{'securityModel'}.' "'. |
|
2639 $meta->{'securityName'}.'" '.$meta->{'securityLevel'}.' '. |
|
2640 $meta->{'storageType'}.' '.$meta->{'rowStatus'}; |
|
2641 } elsif ($directive eq 'targetAddr') { |
|
2642 $line->{'new'} = 'targetAddr "'.$meta->{'targetName'}. |
|
2643 '" '.$meta->{'TDomain'}.' '.$meta->{'TAddress'}. |
|
2644 ' '.$meta->{'timeout'}.' '.$meta->{'retryCount'}. |
|
2645 ' "'.$meta->{'tagList'}.'" "'.$meta->{'paramName'}. |
|
2646 '" '.$meta->{'storageType'}.' '.$meta->{'rowStatus'}; |
|
2647 } elsif ($directive eq 'snmpNotifyTable') { |
|
2648 $line->{'comment'} = '# snmpNotifyTable '.$meta->{'notifyName'}. |
|
2649 ' '.$meta->{'notifyTag'}.' '.$nts{$meta->{'notifyType'}}; |
|
2650 $line->{'new'} = 'snmpNotifyTable "'.$meta->{'notifyName'}. |
|
2651 '" "'.$meta->{'notifyTag'}.'" '.$meta->{'notifyType'}. |
|
2652 ' '.$meta->{'storageType'}.' '.$meta->{'rowStatus'}; |
|
2653 } elsif ($directive eq 'snmpNotifyFilterProfileTable') { |
|
2654 $line->{'new'} = 'snmpNotifyFilterProfileTable "'. |
|
2655 $meta->{'paramName'}.'" "'.$meta->{'profileName'}. |
|
2656 '" '.$meta->{'storageType'}.' '.$meta->{'rowStatus'}; |
|
2657 } elsif ($directive eq 'master') { |
|
2658 $line->{'new'} = 'master '.$meta->{'masterMode'}; |
|
2659 } elsif ($directive eq 'agentxTimeout') { |
|
2660 $line->{'new'} = 'agentxTimeout '.$meta->{'agentxTimeout'}; |
|
2661 } elsif ($directive eq 'agentxRetries') { |
|
2662 $line->{'new'} = 'agentxRetries '.$meta->{'agentxRetries'}; |
|
2663 } |
|
2664 } |
|
2665 } |
|
2666 } |
|
2667 } |
|
2668 |
|
2669 |
|
2670 # convert all rwuser directives to rouser |
|
2671 sub convert_rwusers |
|
2672 { |
|
2673 my ($line, $file); |
|
2674 my ($directive, @tokens); |
|
2675 for $line (get_lines('rwuser', \%::MASF_CONFIGS)) { |
|
2676 $line->{'meta'}->{'directive'} = 'rouser'; |
|
2677 replace_line(\%::MASF_CONFIGS, $line, $line); |
|
2678 } |
|
2679 } |
|
2680 |
|
2681 # convert all rwcommunity directives to rocommunity |
|
2682 sub convert_rwcommunities |
|
2683 { |
|
2684 my ($line); |
|
2685 for $line (get_lines('rwcommunity', \%::MASF_CONFIGS)) { |
|
2686 $line->{'meta'}->{'directive'} = 'rocommunity'; |
|
2687 replace_line(\%::MASF_CONFIGS, $line, $line); |
|
2688 } |
|
2689 } |
|
2690 |
|
2691 sub securityName_from_usmUser |
|
2692 { |
|
2693 my ($directive, @tokens) = @_; |
|
2694 my ($string); |
|
2695 $tokens[3]=~s/^0x//; |
|
2696 $string = pack 'H*', $tokens[3]; |
|
2697 return unpack 'Z*', $string; |
|
2698 } |
|
2699 |
|
2700 sub viewName_exists |
|
2701 { |
|
2702 my ($viewName) = @_; |
|
2703 my ($file, $line, $meta); |
|
2704 for $file (values %::MASF_CONFIGS, values %::SMA_CONFIGS) { |
|
2705 for $line (@$file) { |
|
2706 $meta=$line->{'meta'}; |
|
2707 if ((exists $meta->{'readView'} && |
|
2708 $meta->{'readView'} eq $viewName) || |
|
2709 (exists $meta->{'writeView'} && |
|
2710 $meta->{'writeView'} eq $viewName) || |
|
2711 (exists $meta->{'notifyView'} && |
|
2712 $meta->{'notifyView'} eq $viewName) || |
|
2713 (exists $meta->{'viewName'} && |
|
2714 $meta->{'viewName'} eq $viewName)) { |
|
2715 return 1; |
|
2716 } |
|
2717 } |
|
2718 } |
|
2719 return 0; |
|
2720 } |
|
2721 |
|
2722 sub get_new_viewName |
|
2723 { |
|
2724 my ($prefix)=@_; |
|
2725 my ($viewName, $i); |
|
2726 $i = 0; |
|
2727 |
|
2728 do { |
|
2729 $viewName = $prefix.$i; |
|
2730 if (length $viewName > 32) { |
|
2731 log_message("viewName $viewName was longer than 32 characters\n"); |
|
2732 exit 1; |
|
2733 } |
|
2734 $i++; |
|
2735 } while (viewName_exists($viewName)); |
|
2736 return $viewName; |
|
2737 } |
|
2738 |
|
2739 sub groupName_exists |
|
2740 { |
|
2741 my ($groupName) = @_; |
|
2742 my ($file, $line, $meta); |
|
2743 for $file (values %::MASF_CONFIGS, values %::SMA_CONFIGS) { |
|
2744 for $line (@$file) { |
|
2745 $meta=$line->{'meta'}; |
|
2746 if (exists $meta->{'groupName'} && |
|
2747 $meta->{'groupName'} eq $groupName) { |
|
2748 return 1; |
|
2749 } |
|
2750 } |
|
2751 } |
|
2752 return 0; |
|
2753 } |
|
2754 |
|
2755 sub get_new_groupName |
|
2756 { |
|
2757 my ($prefix)=@_; |
|
2758 my ($groupName, $i); |
|
2759 $i = 0; |
|
2760 |
|
2761 do { |
|
2762 $groupName = $prefix.$i; |
|
2763 if (length $groupName > 32) { |
|
2764 log_message("groupName $groupName was longer than 32 characters\n"); |
|
2765 exit 1; |
|
2766 } |
|
2767 $i++; |
|
2768 } while (groupName_exists($groupName)); |
|
2769 return $groupName; |
|
2770 } |
|
2771 |
|
2772 sub securityName_exists |
|
2773 { |
|
2774 my ($securityName) = @_; |
|
2775 my ($file, $line, $meta); |
|
2776 for $file (values %::MASF_CONFIGS, values %::SMA_CONFIGS) { |
|
2777 for $line (@$file) { |
|
2778 $meta=$line->{'meta'}; |
|
2779 |
|
2780 if (exists $meta->{'securityName'} && |
|
2781 $meta->{'securityName'} eq $securityName) { |
|
2782 return 1; |
|
2783 } |
|
2784 } |
|
2785 } |
|
2786 return 0; |
|
2787 } |
|
2788 |
|
2789 sub get_new_securityName |
|
2790 { |
|
2791 my ($prefix)=@_; |
|
2792 my ($securityName, $i); |
|
2793 $i = 0; |
|
2794 |
|
2795 do { |
|
2796 $securityName = $prefix.$i; |
|
2797 # check to see if length is more than 32 characters permitted |
|
2798 # by VACM |
|
2799 if (length $securityName > 32) { |
|
2800 log_message("securityName $securityName was longer". |
|
2801 " than 32 characters\n"); |
|
2802 exit 1; |
|
2803 } |
|
2804 |
|
2805 $i++; |
|
2806 } while (securityName_exists($securityName)); |
|
2807 return $securityName; |
|
2808 } |
|
2809 |
|
2810 sub expand_rouser |
|
2811 { |
|
2812 my ($line, $default_oids) = @_; |
|
2813 my ($securityName, $groupName, $viewName, $secLevel, $oid); |
|
2814 my (@output, $readView, $writeView, $i); |
|
2815 @output = ($line); |
|
2816 $securityName = $line->{'meta'}->{'securityName'}; |
|
2817 if (! defined $line->{'meta'}->{'securityLevel'}) { |
|
2818 $secLevel = "auth"; |
|
2819 } else { |
|
2820 $secLevel = $line->{'meta'}->{'securityLevel'}; |
|
2821 } |
|
2822 if (! defined $line->{'meta'}->{'oid'}) { |
|
2823 $oid = ''; |
|
2824 } else { |
|
2825 $oid = $line->{'meta'}->{'oid'}; |
|
2826 } |
|
2827 |
|
2828 $groupName = get_new_groupName("Group"); |
|
2829 $viewName = get_new_viewName("View"); |
|
2830 |
|
2831 if ($line->{'meta'}->{'directive'} eq 'rouser') { |
|
2832 $readView = $viewName; |
|
2833 $writeView = ''; |
|
2834 } else { |
|
2835 $readView = $viewName; |
|
2836 $writeView = $viewName; |
|
2837 } |
|
2838 |
|
2839 $output[0]->{'meta'} = {'directive'=>'group', |
|
2840 'groupName'=>$groupName, |
|
2841 'securityModel'=>'usm', |
|
2842 'securityName'=>$securityName}; |
|
2843 push @output, {'meta'=>{'directive'=>'access', |
|
2844 'groupName'=>$groupName, |
|
2845 'contextPrefix'=>'', |
|
2846 'securityModel'=>'usm', |
|
2847 'securityLevel'=>$secLevel, |
|
2848 'contextMatch'=>'exact', |
|
2849 'readView'=>$readView, |
|
2850 'writeView'=>$writeView, |
|
2851 'notifyView'=>''} |
|
2852 }; |
|
2853 if ($oid ne '') { |
|
2854 push @output, {'meta'=>{'directive'=>'view', |
|
2855 'viewName'=>$viewName, |
|
2856 'viewType'=>'included', |
|
2857 'oid'=>$oid}}; |
|
2858 } else { |
|
2859 for ($i = 0; $i < @$default_oids; $i++) { |
|
2860 push @output,{'meta'=>{'directive'=>'view', |
|
2861 'viewName'=>$viewName, |
|
2862 'viewType'=>'included', |
|
2863 'oid'=>$default_oids->[$i]}}; |
|
2864 } |
|
2865 } |
|
2866 return @output; |
|
2867 } |
|
2868 |
|
2869 sub expand_rocommunity |
|
2870 { |
|
2871 my ($line, $default_oids) = @_; |
|
2872 my ($securityName, $groupName, $viewName, $community, $source, $oid); |
|
2873 my (@output, $readView, $writeView, $i); |
|
2874 @output = ($line); |
|
2875 $community = $line->{'meta'}->{'community'}; |
|
2876 $source = $line->{'meta'}->{'source'}; |
|
2877 if (defined $line->{'meta'}->{'oid'}) { |
|
2878 $oid = $line->{'meta'}->{'oid'}; |
|
2879 } else { |
|
2880 $oid = ''; |
|
2881 } |
|
2882 |
|
2883 $securityName = get_new_securityName("User"); |
|
2884 $groupName = get_new_groupName("Group"); |
|
2885 $viewName = get_new_viewName("View"); |
|
2886 |
|
2887 if ($line->{'meta'}->{'directive'} eq 'rocommunity') { |
|
2888 $readView = $viewName; |
|
2889 $writeView = ''; |
|
2890 } else { |
|
2891 $readView = $viewName; |
|
2892 $writeView = $viewName; |
|
2893 } |
|
2894 |
|
2895 $output[0]->{'meta'} = {'directive'=>"com2sec", |
|
2896 'securityName'=>$securityName, |
|
2897 'source'=>$source, |
|
2898 'community'=>$community |
|
2899 }; |
|
2900 push @output, {'meta'=>{'directive'=>'group', |
|
2901 'groupName'=>$groupName, |
|
2902 'securityModel'=>'v1', |
|
2903 'securityName'=>$securityName} |
|
2904 }, |
|
2905 {'meta'=>{'directive'=>'group', |
|
2906 'groupName'=>$groupName, |
|
2907 'securityModel'=>'v2c', |
|
2908 'securityName'=>$securityName} |
|
2909 }, |
|
2910 {'meta'=>{'directive'=>'access', |
|
2911 'groupName'=>$groupName, |
|
2912 'contextPrefix'=>'', |
|
2913 'securityModel'=>'v1', |
|
2914 'securityLevel'=>'noauth', |
|
2915 'contextMatch'=>'exact', |
|
2916 'readView'=>$readView, |
|
2917 'writeView'=>$writeView, |
|
2918 'notifyView'=>''} |
|
2919 }, |
|
2920 {'meta'=>{'directive'=>'access', |
|
2921 'groupName'=>$groupName, |
|
2922 'contextPrefix'=>'', |
|
2923 'securityModel'=>'v2c', |
|
2924 'securityLevel'=>'noauth', |
|
2925 'contextMatch'=>'exact', |
|
2926 'readView'=>$readView, |
|
2927 'writeView'=>$writeView, |
|
2928 'notifyView'=>''} |
|
2929 }; |
|
2930 if ($oid ne '') { |
|
2931 push @output, {'meta'=>{'directive'=>'view', |
|
2932 'viewName'=>$viewName, |
|
2933 'viewType'=>'included', |
|
2934 'oid'=>$oid}}; |
|
2935 } else { |
|
2936 for ($i = 0; $i < @$default_oids; $i++) { |
|
2937 push @output, {'meta'=>{'directive'=>'view', |
|
2938 'viewName'=>$viewName, |
|
2939 'viewType'=>'included', |
|
2940 'oid'=>$default_oids->[$i]}}; |
|
2941 } |
|
2942 } |
|
2943 return @output; |
|
2944 } |
|
2945 |
|
2946 sub expand_rousers |
|
2947 { |
|
2948 my ($configs, $default_oids) = @_; |
|
2949 my ($file, $lines, $i, $output, $line, $directive, @tokens); |
|
2950 my (@expanded); |
|
2951 for $file (keys %$configs) { |
|
2952 $lines = $configs->{$file}; |
|
2953 $output=[]; |
|
2954 for ($i = 0; $i < @$lines; $i++) { |
|
2955 $line = $lines->[$i]; |
|
2956 if (! exists $line->{'meta'}->{'directive'}) { |
|
2957 next; |
|
2958 } |
|
2959 $directive = $line->{'meta'}->{'directive'}; |
|
2960 if ($directive eq 'rouser' || $directive eq 'rwuser') { |
|
2961 # expand rocommunity directive |
|
2962 @expanded = expand_rouser($line, $default_oids); |
|
2963 splice @$lines, $i, 1, @expanded; |
|
2964 $i += $#expanded; |
|
2965 } |
|
2966 } |
|
2967 } |
|
2968 } |
|
2969 |
|
2970 sub expand_rocommunities |
|
2971 { |
|
2972 my ($configs, $default_oids)= @_; |
|
2973 my ($file, $lines, $i, $output, $line, $directive, @tokens); |
|
2974 my (@expanded); |
|
2975 for $file (keys %$configs) { |
|
2976 $lines = $configs->{$file}; |
|
2977 $output=[]; |
|
2978 for ($i = 0; $i < @$lines; $i++) { |
|
2979 $line = $lines->[$i]; |
|
2980 if (! exists $line->{'meta'}->{'directive'}) { |
|
2981 next; |
|
2982 } |
|
2983 |
|
2984 if ($line->{'meta'}->{'directive'} eq 'rocommunity' || |
|
2985 $line->{'meta'}->{'directive'} eq 'rwcommunity') { |
|
2986 # expand rocommunity directive |
|
2987 @expanded = expand_rocommunity($line, $default_oids); |
|
2988 splice @$lines, $i, 1, @expanded; |
|
2989 $i += $#expanded; |
|
2990 } |
|
2991 } |
|
2992 } |
|
2993 } |
|
2994 |
|
2995 ############################################################################## |
|
2996 # General configuration |
|
2997 |
|
2998 sub install_agentx_config |
|
2999 { |
|
3000 my (@lines) = get_lines('master', \%::SMA_CONFIGS); |
|
3001 if (@lines) { |
|
3002 if (grep (($lines[0]->{'meta'}->{'masterMode'} eq $_), |
|
3003 ('agentx', 'all', 'yes', 'on'))) { |
|
3004 # master mode is enabled anyway |
|
3005 } else { |
|
3006 # master mode was disabled! |
|
3007 log_message "AgentX mastering capability has been explicitly ". |
|
3008 "disabled in the SMA config - Aborting.\n", $lines[0]; |
|
3009 exit 1; |
|
3010 } |
|
3011 } else { |
|
3012 # master mode has not been specified, add it. |
|
3013 log_message "Enabling agentX mastering for SMA.\n"; |
|
3014 prepend_line({'meta'=>{'directive'=>'master', 'masterMode'=>'agentx'}}); |
|
3015 } |
|
3016 @lines = get_lines('agentxTimeout', \%::SMA_CONFIGS); |
|
3017 if (@lines) { |
|
3018 if ($lines[0]->{'agentxTimeout'} < 2) { |
|
3019 $lines[0]->{'agentxTimeout'} = 2; |
|
3020 replace_line(\%::SMA_CONFIGS, $lines[0], $lines[0]); |
|
3021 } |
|
3022 } else { |
|
3023 prepend_line({'meta'=>{'directive'=>'agentxTimeout', 'agentxTimeout'=>2}}); |
|
3024 } |
|
3025 @lines = get_lines('agentxRetries', \%::SMA_CONFIGS); |
|
3026 if (@lines) { |
|
3027 if ($lines[0]->{'agentxRetries'} < 4) { |
|
3028 $lines[0]->{'agentxRetries'} = 4; |
|
3029 replace_line(\%::SMA_CONFIGS, $lines[0], $lines[0]); |
|
3030 } |
|
3031 } else { |
|
3032 prepend_line({'meta'=>{'directive'=>'agentxRetries', 'agentxRetries'=>4}}); |
|
3033 } |
|
3034 } |
|
3035 |
|
3036 sub check_agent_configs |
|
3037 { |
|
3038 my ($directive, $line); |
|
3039 for $directive ('agentgroup', 'agentuser', 'authtrapenable') { |
|
3040 my (@masf) = get_lines($directive, \%::MASF_CONFIGS); |
|
3041 my (@sma) = get_lines($directive, \%::SMA_CONFIGS); |
|
3042 if (@masf > 0 && @sma == 0) { |
|
3043 log_message "The following $directive directive was found in ". |
|
3044 "the MASF configuration but is not configured for SMA:\n"; |
|
3045 log_message $masf[0]->{'new'}."\n"; |
|
3046 |
|
3047 } elsif (@masf > 0 && @sma > 0 && $sma[0] ne $masf[0]) { |
|
3048 log_message "The following $directive directive was found in ". |
|
3049 "the MASF configuration but differs in the SMA configuration:\n"; |
|
3050 log_message $masf[0]->{'new'}."\n"; |
|
3051 } |
|
3052 for $line (@masf) { |
|
3053 # delete the line |
|
3054 replace_line(\%::MASF_CONFIGS, $line, {'meta'=>{}}); |
|
3055 } |
|
3056 } |
|
3057 } |
|
3058 |
|
3059 sub check_system_configs |
|
3060 { |
|
3061 my ($directive, $line); |
|
3062 for $directive ('syslocation', 'syscontact', 'sysname', 'sysservices') { |
|
3063 my (@masf) = get_lines($directive, \%::MASF_CONFIGS); |
|
3064 my (@sma) = get_lines($directive, \%::SMA_CONFIGS); |
|
3065 if (@masf > 0 && @sma == 0) { |
|
3066 log_message "The following $directive directive was found in ". |
|
3067 "the MASF configuration but is not configured for SMA:\n"; |
|
3068 log_message $masf[0]->{'new'}."\n"; |
|
3069 log_message "You may wish to set this parameter in the SMA ". |
|
3070 "configuration file after this script completes migration.\n"; |
|
3071 |
|
3072 } elsif (@masf > 0 && @sma > 0 && $sma[0]->{'new'} ne $masf[0]->{'new'}) { |
|
3073 log_message "The following $directive directive was found in ". |
|
3074 "the MASF configuration but differs in the SMA configuration:\n"; |
|
3075 log_message $masf[0]->{'new'}."\n"; |
|
3076 log_message "You may wish to set this parameter in the SMA ". |
|
3077 "configuration file after this script completes migration.\n"; |
|
3078 } |
|
3079 for $line (@masf) { |
|
3080 # delete the line |
|
3081 replace_line(\%::MASF_CONFIGS, $line, {'meta'=>{}}); |
|
3082 } |
|
3083 } |
|
3084 } |
|
3085 |
|
3086 sub process_agentaddress |
|
3087 { |
|
3088 my ($line, $lines, @masfAgentAddress, $smaAgentAddress, $config); |
|
3089 (@masfAgentAddress) = get_lines ('agentaddress', \%::MASF_CONFIGS); |
|
3090 if (@masfAgentAddress == 0) { |
|
3091 log_message "No agentaddress directive found for MASF\n"; |
|
3092 return; |
|
3093 } |
|
3094 |
|
3095 # if more than one MASF agentaddress line was specified then all but the |
|
3096 # last are ignored so we should delete them |
|
3097 while (@masfAgentAddress > 1) { |
|
3098 $line = shift @masfAgentAddress; |
|
3099 replace_line (\%::MASF_CONFIGS, $line, {'meta'=>{}}); |
|
3100 } |
|
3101 |
|
3102 my (@smaTokens, @masfTokens); |
|
3103 ($smaAgentAddress) = get_lines ('agentaddress', \%::SMA_CONFIGS); |
|
3104 if (! defined $smaAgentAddress) { |
|
3105 log_message "SMA uses default 161 port\n"; |
|
3106 @smaTokens = ('udp:161'); |
|
3107 } else { |
|
3108 @smaTokens = parse_agentaddress ($smaAgentAddress->{'new'}); |
|
3109 } |
|
3110 |
|
3111 if (defined $smaAgentAddress) { |
|
3112 $line = $smaAgentAddress; |
|
3113 $config = \%::SMA_CONFIGS; |
|
3114 } else { |
|
3115 $line = $masfAgentAddress[0]; |
|
3116 $config = \%::MASF_CONFIGS; |
|
3117 } |
|
3118 |
|
3119 if ($::DISABLE_MASF_PORT && @masfAgentAddress) { |
|
3120 log_message "Disabling access via old MASF port\n"; |
|
3121 delete $masfAgentAddress[0]->{'new'}; |
|
3122 return; |
|
3123 } |
|
3124 |
|
3125 @masfTokens = parse_agentaddress ($masfAgentAddress[0]->{'new'}); |
|
3126 |
|
3127 # MASF addresses must be a subset of SMA |
|
3128 my ($i, $j, $okToMigrate); |
|
3129 $okToMigrate = 1; |
|
3130 for $i (@masfTokens) { |
|
3131 if (grep(($i eq $_), @smaTokens) == 0) { |
|
3132 log_message "MASF port configuration for port $i conflicts with SMA\n"; |
|
3133 $okToMigrate = 0; |
|
3134 } |
|
3135 } |
|
3136 |
|
3137 if (! $okToMigrate && ! $::USE_MASF_PORT && ! $::DISABLE_MASF_PORT) { |
|
3138 log_message "Unable to resolve conflict - aborting\n"; |
|
3139 exit 1; |
|
3140 } |
|
3141 |
|
3142 if ($::USE_MASF_PORT) { |
|
3143 push @smaTokens, @masfTokens; |
|
3144 } |
|
3145 $line->{'new'} = 'agentaddress '.(join ',',@smaTokens); |
|
3146 replace_line($config, $line, $line); |
|
3147 return; |
|
3148 } |
|
3149 |
|
3150 ############################################################################## |
|
3151 # Main section starts here |
|
3152 |
|
3153 # configure Getopt for CLIP compliance |
|
3154 Getopt::Long::Configure('bundling', 'require_order', |
|
3155 'no_getopt_compat', 'no_auto_abbrev', 'no_ignore_case'); |
|
3156 |
|
3157 my ($selectCommunity, $selectUser, $useAgentPort, $trapFilter, |
|
3158 $masterTrapTarget, $version, $help); |
|
3159 $selectCommunity = 'error'; |
|
3160 $selectUser = 'error'; |
|
3161 $useAgentPort = 'error'; |
|
3162 $trapFilter = 'add'; |
|
3163 |
|
3164 my $result = GetOptions( |
|
3165 'i|ignore-unrecognized-directives'=>\$::IGNORE_UNRECOGNIZED_DIRECTIVES, |
|
3166 's|skip-user'=>\$::IGNORE_ENGINEID, |
|
3167 'y|select-community=s'=>\$selectCommunity, |
|
3168 'u|select-user=s'=>\$selectUser, |
|
3169 'p|use-agent-port=s'=>\$useAgentPort, |
|
3170 't|trap-filter=s'=>\$trapFilter, |
|
3171 'l|master-trap-target=s'=>\$masterTrapTarget, |
|
3172 'c|no-community'=>\$::DONT_KEEP_V1V2C_USERS, |
|
3173 'r|no-trap'=>\$::DONT_KEEP_TRAP_DESTS, |
|
3174 'm|no-usmuser'=>\$::DONT_KEEP_V3_USERS, |
|
3175 'n|dry-run'=>\$::DRY_RUN, |
|
3176 'V|version'=>\$version, |
|
3177 'help|?'=>\$help); |
|
3178 |
|
3179 if (! $result) { |
|
3180 print STDERR "An unrecognized option was present.\n"; |
|
3181 help(); |
|
3182 } |
|
3183 |
|
3184 if ($version) { |
|
3185 version(); |
|
3186 } |
|
3187 |
|
3188 # no interactive mode |
|
3189 $::AUTOMATED = 1; |
|
3190 |
|
3191 $::KEEP_MASF_GROUPS = 0; |
|
3192 $::KEEP_SMA_GROUPS = 0; |
|
3193 if ($selectCommunity eq 'agent') { |
|
3194 $::KEEP_MASF_GROUPS = 1; |
|
3195 } elsif ($selectCommunity eq 'master') { |
|
3196 $::KEEP_SMA_GROUPS = 1; |
|
3197 } elsif ($selectCommunity ne 'error') { |
|
3198 print STDERR "Invalid --select-community option $selectCommunity". |
|
3199 " specified.\n"; |
|
3200 help(); |
|
3201 } |
|
3202 |
|
3203 $::KEEP_MASF_USM_USERS = 0; |
|
3204 $::KEEP_SMA_USM_USERS = 0; |
|
3205 if ($selectUser eq 'agent') { |
|
3206 $::KEEP_MASF_USM_USERS = 1; |
|
3207 } elsif ($selectUser eq 'master') { |
|
3208 $::KEEP_SMA_USM_USERS = 1; |
|
3209 } elsif ($selectUser ne 'error') { |
|
3210 print STDERR "Invalid --select-user option $selectUser". |
|
3211 " specified.\n"; |
|
3212 help(); |
|
3213 } |
|
3214 |
|
3215 $::USE_MASF_PORT = 0; |
|
3216 $::DISABLE_MASF_PORT = 0; |
|
3217 if ($useAgentPort eq 'enable') { |
|
3218 $::USE_MASF_PORT = 1; |
|
3219 } elsif ($useAgentPort eq 'disable') { |
|
3220 $::DISABLE_MASF_PORT = 1; |
|
3221 } elsif ($useAgentPort ne 'error') { |
|
3222 print STDERR "Invalid --use-agent-port option $useAgentPort specified\n"; |
|
3223 help(); |
|
3224 } |
|
3225 |
|
3226 if ($trapFilter eq 'none') { |
|
3227 $::NO_TRAP_FILTERS = 1; |
|
3228 } elsif ($trapFilter eq 'add') { |
|
3229 $::NO_TRAP_FILTERS = 0; |
|
3230 } else { |
|
3231 print STDERR "Invalid --trap-filter option $trapFilter\n"; |
|
3232 help(); |
|
3233 } |
|
3234 |
|
3235 $::EXTEND_SMA_FILTERS = 0; |
|
3236 $::KEEP_SNMP_TARGET_PARAMS = 0; |
|
3237 if (defined $masterTrapTarget) { |
|
3238 if ($trapFilter eq 'none') { |
|
3239 print STDERR "--master-trap-target cannot be used with --trap-filter=none\n"; |
|
3240 help(); |
|
3241 } |
|
3242 if ($masterTrapTarget eq 'agent') { |
|
3243 $::EXTEND_SMA_FILTERS = 1; |
|
3244 } elsif ($masterTrapTarget eq 'master') { |
|
3245 $::KEEP_SNMP_TARGET_PARAMS = 1; |
|
3246 $::EXTEND_SMA_FILTERS = 1; |
|
3247 } else { |
|
3248 print STDERR "Invalid --master-trap-target option $masterTrapTarget specified.\n"; |
|
3249 help(); |
|
3250 } |
|
3251 } |
|
3252 |
|
3253 if ($help) { |
|
3254 help(); |
|
3255 } |
|
3256 |
|
3257 # set the umask before writing to the log file |
|
3258 set_umask(); |
|
3259 log_message "masfcnv ".localtime()."\n\n"; |
|
3260 are_we_root(); |
|
3261 stop_sma_running(); |
|
3262 stop_masf_running(); |
|
3263 |
|
3264 @::MASF_CONFIG_FILES = ("/etc/opt/SUNWmasf/conf/snmpd.conf"); |
|
3265 $::MASF_PERSISTENT_FILE = "/var/opt/SUNWmasf/snmpd.dat"; |
|
3266 $::MASF_PERSISTENT_DIR = "/var/opt/SUNWmasf"; |
|
3267 |
|
3268 @::SMA_CONFIG_FILES = ("/usr/lib/net-snmp/snmpd.conf"); |
|
3269 $::SMA_PERSISTENT_FILE = "/var/net-snmp/snmpd.conf"; |
|
3270 $::SMA_PERSISTENT_DIR = "/var/net-snmp"; |
|
3271 sma_config_sanity_check(); |
|
3272 masf_config_sanity_check(); |
|
3273 read_config_files(); |
|
3274 sanity_check_config_files(); |
|
3275 add_metadata(); |
|
3276 install_agentx_config(); |
|
3277 process_agentaddress(); |
|
3278 convert_rwcommunities(); |
|
3279 expand_rocommunities(\%::MASF_CONFIGS, [$ENTITY_MIB_OID, $SUNPLAT_MIB_OID]); |
|
3280 expand_rocommunities(\%::SMA_CONFIGS, [$INTERNET_OID]); |
|
3281 convert_rwusers(); |
|
3282 expand_rousers(\%::MASF_CONFIGS, [$ENTITY_MIB_OID, $SUNPLAT_MIB_OID]); |
|
3283 expand_rousers(\%::SMA_CONFIGS, [$INTERNET_OID]); |
|
3284 clean_group_membership(); |
|
3285 if (! $::DONT_KEEP_V1V2C_USERS) { |
|
3286 uniquify_securityNames('masf'); |
|
3287 process_com2sec(); |
|
3288 } else { |
|
3289 remove_v1v2c_users(); |
|
3290 } |
|
3291 uniquify_groupNames('masf'); |
|
3292 check_usm_securityNames(); |
|
3293 process_engineIDs(); |
|
3294 if (! $::DONT_KEEP_V3_USERS) { |
|
3295 process_usm_securityNames(); |
|
3296 } else { |
|
3297 remove_v3_users(); |
|
3298 } |
|
3299 uniquify_viewNames('masf'); |
|
3300 |
|
3301 process_trapcommunity(\%::MASF_CONFIGS); |
|
3302 process_trapcommunity(\%::SMA_CONFIGS); |
|
3303 if ($::DONT_KEEP_TRAP_DESTS) { |
|
3304 remove_trap_destinations(); |
|
3305 } |
|
3306 check_duplicate_trap_destinations(); |
|
3307 if ($::NO_TRAP_FILTERS) { |
|
3308 # simplistic trap processing |
|
3309 # no further filtering |
|
3310 } else { |
|
3311 |
|
3312 if ($::EXTEND_SMA_FILTERS) { |
|
3313 # "master" |
|
3314 # if the administrator selects EXTEND_SMA_FILTERS and |
|
3315 # KEEP_SNMP_TARGET_PARAMS is selected then: MASF trap destinations are |
|
3316 # migrated using existing SMA targetParams, targetAddrs, filterProfiles |
|
3317 # if possible. SMA trap destinations keep existing targetParams and |
|
3318 # have filterProfiles updated to INCLUDE MASF traps. Targets present in |
|
3319 # both SMA and MASF configs end up receiving all traps with SMA params. |
|
3320 # 1. Update SMA filterProfiles to include MASF traps |
|
3321 # 2. Expand existing MASF trapsinks to targetAddrs, params, and profiles |
|
3322 # identifying overlapping trap destinations and using them where |
|
3323 # appropriate |
|
3324 |
|
3325 # "agent" |
|
3326 # if the administrator selects EXTEND_SMA_FILTERS and |
|
3327 # KEEP_SNMP_TARGET_PARAMS is not selected then: MASF trap destinations |
|
3328 # are migrated using MASF targetParams, targetAddrs, filterProfiles. |
|
3329 # All SMA trap destinations not in MASF use SMA params and have MASF |
|
3330 # traps INCLUDED. New params are created for targets present in both |
|
3331 # SMA and MASF which use tag specifically for MASF. Targets present in |
|
3332 # both SMA and MASF configs end up receiving all traps with MASF params. |
|
3333 # 1. Update SMA filterProfiles to include MASF traps |
|
3334 # 2. Expand existing MASF trapsinks to new targetAddrs, params, |
|
3335 # profiles, identifying overlapping trap destinations and profiles, |
|
3336 # transferring them to new SMA params and retain original profiles. |
|
3337 |
|
3338 # selecting KEEP_SNMP_TARGET_PARAMS without EXTEND_SMA_FILTERS is not an |
|
3339 # option |
|
3340 extend_sma_trap_filters(); |
|
3341 } |
|
3342 # "add" |
|
3343 # if the administrator selects neither option then: All MASF trap |
|
3344 # configurations are translated to new params, targetAddrs, filters which |
|
3345 # have ONLY MASF traps included in the profile. Targets present in both |
|
3346 # MASF and SMA may receive duplicate traps, depending upon the SMA filter |
|
3347 # profile. |
|
3348 # 1. Expand existing MASF trapsinks to new targetAddrs, params, profiles. |
|
3349 process_trapsinks(); |
|
3350 } |
|
3351 check_system_configs(); |
|
3352 check_agent_configs(); |
|
3353 convert_metadata(); |
|
3354 if (! $::DRY_RUN) { |
|
3355 backup_files(); |
|
3356 remove_masf_persistent_file(); |
|
3357 } |
|
3358 if ($::DRY_RUN) { |
|
3359 print "Contents of ".$::SMA_CONFIG_FILES[0]."\n"; |
|
3360 print "\n"; |
|
3361 *FH = *STDOUT; |
|
3362 } else { |
|
3363 open (FH, "> ".$::SMA_CONFIG_FILES[0]) || die "Couldn't open file ".$::SMA_CONFIG_FILES[0]." for writing.\n"; |
|
3364 } |
|
3365 my ($l); |
|
3366 for $l (@{$::ADDED_CONFIGS{'prepend'}}) { |
|
3367 print_line (\*FH, $l); |
|
3368 } |
|
3369 dump_config(\*FH, $::SMA_PERSISTENT_FILE, \%::SMA_CONFIGS); |
|
3370 dump_config(\*FH, $::MASF_PERSISTENT_FILE, \%::MASF_CONFIGS); |
|
3371 for $l (@{$::ADDED_CONFIGS{'append'}}) { |
|
3372 print_line (\*FH, $l); |
|
3373 } |
|
3374 if ($::DRY_RUN) { |
|
3375 print "=======================\n"; |
|
3376 print "Contents of ".$::SMA_PERSISTENT_FILE."\n"; |
|
3377 print "=======================\n"; |
|
3378 } else { |
|
3379 close FH; |
|
3380 open (FH, "> ".$::SMA_PERSISTENT_FILE) || die "Couldn't open file ".$::SMA_PERSISTENT_FILE." for writing.\n"; |
|
3381 } |
|
3382 dump_persistent_storage(\*FH, $::SMA_PERSISTENT_FILE, \%::SMA_CONFIGS); |
|
3383 dump_persistent_storage(\*FH, $::MASF_PERSISTENT_FILE, \%::MASF_CONFIGS); |
|
3384 if (! $::DRY_RUN) { |
|
3385 close FH; |
|
3386 install_template_config_file(); |
|
3387 install_new_wrapper_script(); |
|
3388 } |