1# $Id: sonde-stp-catalyst.pl,v 1.1.1.1 2008/06/13 08:55:51 pda Exp $
2#
3#
4# ###################################################################
5# boggia : Creation : 27/03/08
6#
7# fonctions qui permettent de r�cup�rer en SNMP l'etat du spanning
8# tree sur les commutateurs Cisco
9#
10# Resultats possibles de requetes :
11#   1 - disabled
12#   2 - blocking
13#   3 - listening
14#   4 - learning
15#   5 - forwarding
16#   6 - broken
17
18sub get_stp_catalyst
19{
20    my ($base,$host,$community,$l_param) = @_;
21
22    my @fichier = ();
23    # teste si l'equipement est toujours en cours d'interrogation
24    #print "($host,$community,$l_param)\n";
25    opendir(REPLOCK,$config{'dir_lock'});
26    @fichier = grep(/$host/,readdir REPLOCK);
27    closedir(REPLOCK);
28
29    # si pas de lock
30    if(! $fichier[0])
31    {
32	open(LOCK,">$config{'dir_lock'}/$host.lock");
33        close(LOCK);
34
35	my $dir_result = "$config{'dir_res_stp'}";
36        open(FICH,">$dir_result/$host");
37	close(FICH);
38
39	my ($snmp, $error) = Net::SNMP->session(
40                -hostname       => $host,
41                -community      => $community,
42                -port           => 161,
43                -timeout        => $config{"snmp_timeout"},
44                -retries        => 2,
45                -nonblocking    => 0x1,
46                -version        => "2c" );
47
48	if (!defined($snmp))
49	{
50	    #writelog("get_stp_catalyst",$config{syslog_facility},"info",
51            #     "\t -> ERROR: SNMP connect error: $error");
52	}
53	else
54	{
55	    my $bridgeOid = "1.3.6.1.2.1.17.1.1.0";
56	    my $r = $snmp->get_request(
57                -varbindlist   => [$bridgeOid],
58                -callback   => [ \&get_snmp_bridge_id,$host,$community,$l_param,$bridgeOid] );
59	}
60
61	unlink "$config{'dir_lock'}/$host.lock";
62    }
63    else
64    {
65	#writelog("get_stp_catalyst",$config{syslog_facility},"info",
66        #         "\t -> WARNING : $host toujours en cours d'interrogation");
67    }
68}
69
70
71sub get_snmp_bridge_id
72{
73    my ($session,$host,$communaute,$liste_vlans,$bridgeOid) = @_;
74
75    if (!defined($session->var_bind_list))
76    #l'equipement ne repond pas
77    {
78        my $error  = $session->error;
79        #writelog("get_stp_catalyst",$config{syslog_facility},"info",
80        #         "\t -> ERROR: get_stp_catalyst($host) Error: $error");
81        #print "ERROR: get_stp_catalyst($host) Error: $error\n";
82    }
83    else
84    # l'equipement repond
85    {
86        # repertoire dans lequel seront stockes les resultats
87        my $elem;
88
89        my $bridgeId = $session->var_bind_list->{$bridgeOid};
90
91        $bridgeId = set_Id2Mac($bridgeId);
92
93	$BridgeID{$bridgeId} = $host;
94        #print "\nget_snmp_bridge_id($host,$communaute) bridgeId = $bridgeId";
95
96        my @vlans = split(/:/,$liste_vlans);
97
98        foreach $elem (@vlans)
99        {
100            if($elem=~/[0-9]+/)
101            {
102                #print "vlan $elem :\n";
103
104                my $community = "$communaute\@$elem";
105
106                my ($snmp, $error) = Net::SNMP->session(
107                    -hostname       => $host,
108                    -community      => $community,
109                    -port           => 161,
110                    -timeout        => $config{"snmp_timeout"},
111                    -retries        => 2,
112                    -nonblocking    => 0x1,
113                    -version        => "2c" );
114
115                if (!defined($snmp))
116                {
117                    #writelog("get_assoc_ap",$config{syslog_facility},"info",
118                    #    "\t -> ERROR: SNMP connect error: $error");
119                    #print "ERROR: SNMP connect error: $error\n";
120                }
121                else
122                {
123                    #recuperation de la racine du spanning Tree
124		    my $rootBridgeOid = "1.3.6.1.2.1.17.2.5.0";
125		    my $r = $snmp->get_request(
126			-varbindlist   => [$rootBridgeOid],
127			-callback   => [ \&get_snmp_rootBridge,$host,$community,$elem,$rootBridgeOid,$bridgeId] );
128                }
129            }
130        }
131    }
132}
133
134
135sub get_snmp_rootBridge
136{
137    my ($session,$host,$community,$vlan,$rootBridgeOid,$bridgeId) = @_;
138
139    if (!defined($session->var_bind_list))
140    #l'equipement ne repond pas
141    {
142        my $error  = $session->error;
143        #writelog("get_stp_catalyst",$config{syslog_facility},"info",
144        #         "\t -> ERROR: get_stp_catalyst($host) Error: $error");
145        #print "ERROR: get_stp_catalyst($host) Error: $error\n";
146    }
147    else
148    # l'equipement repond
149    {
150        # repertoire dans lequel seront stockes les resultats
151        my $rootBridgeId = $session->var_bind_list->{$rootBridgeOid};
152
153        $rootBridgeId = set_Id2Mac($rootBridgeId);
154
155	#print "\nget_snmp_rootBridge($host,$community,$vlan,$rootBridgeOid) rootBridgeId = $rootBridgeId";
156        #print "\nget_stp_catalyst($host) $bridgeId = $bridgeId";
157
158        my ($snmp, $error) = Net::SNMP->session(
159	    -hostname       => $host,
160            -community      => $community,
161            -port           => 161,
162            -timeout        => $config{"snmp_timeout"},
163            -retries        => 2,
164            -nonblocking    => 0x1,
165            -version        => "2c" );
166
167        if (!defined($snmp))
168        {
169	    #writelog("get_assoc_ap",$config{syslog_facility},"info",
170	    #    "\t -> ERROR: SNMP connect error: $error");
171            ##print "ERROR: SNMP connect error: $error\n";
172        }
173        else
174        {
175            #recuperation du Root Port
176            my $rootPortOid = "1.3.6.1.2.1.17.2.7.0";
177            my $r = $snmp->get_request(
178		-varbindlist   => [$rootPortOid],
179                -callback   => [ \&get_snmp_rootPort,$host,$community,$vlan,$rootPortOid,$bridgeId,$rootBridgeId] );
180        }
181    }
182}
183
184
185sub get_snmp_rootPort
186{
187    my ($session,$host,$community,$vlan,$rootPortOid,$bridgeId,$rootBridgeId) = @_;
188
189    if (!defined($session->var_bind_list))
190    #l'equipement ne repond pas
191    {
192        my $error  = $session->error;
193        #writelog("get_stp_catalyst",$config{syslog_facility},"info",
194        #         "\t -> ERROR: get_stp_catalyst($host) Error: $error");
195	#print "ERROR: get_stp_catalyst($host) Error: $error\n";
196    }
197    else
198    # l'equipement repond
199    {
200	my $rootPort = $session->var_bind_list->{$rootPortOid};
201        #print "\nget_stp_catalyst($host) $bridgeId = $bridgeId";
202
203	my ($snmp, $error) = Net::SNMP->session(
204	    -hostname       => $host,
205	    -community      => $community,
206	    -port           => 161,
207	    -timeout        => $config{"snmp_timeout"},
208	    -retries        => 2,
209	    -nonblocking    => 0x1,
210	    -version        => "2c" );
211
212	if (!defined($snmp))
213	{
214	    #writelog("get_assoc_ap",$config{syslog_facility},"info",
215                   #    "\t -> ERROR: SNMP connect error: $error");
216	    #print "ERROR: SNMP connect error: $error\n";
217	}
218	else
219	{
220	    my $state_oid = '1.3.6.1.2.1.17.2.15.1.3';
221	    my $res = $snmp->get_table(
222		$state_oid,
223		-callback   => [ \&get_snmp_port_state,$host,$community,$vlan,$state_oid,$bridgeId,$rootBridgeId,$rootPort] );
224	}
225    }
226}
227
228
229sub get_snmp_port_state
230{
231    my ($session,$host,$community,$vlan,$state_oid,$bridgeId,$rootBridgeId,$rootPort) = @_;
232
233    if(defined($session->var_bind_list()))
234    {
235	# Extract the response.
236        my $key = '';
237        my $hashref = $session->var_bind_list();
238	my $compteur = 0;
239
240	my $dir_result = "$config{'dir_res_stp'}";
241	open(FICH,">>$dir_result/$host");
242
243	print FICH "\nVlan$vlan bridgeId=$bridgeId\n";
244	print FICH "Vlan$vlan rootBridgeId=$rootBridgeId ($BridgeID{$rootBridgeId})\n";
245
246	$stpInfos{"$host:$vlan:bridgeId"} = $bridgeId;
247	$stpInfos{"$host:$vlan:rootBridgeId"} = $rootBridgeId;
248
249	my $param = $community."@".$host;
250
251        foreach $key (keys %$hashref)
252        {
253	    my $nom_interf;
254
255	    $compteur ++;
256	    chomp($key);
257
258	    my @decomp_oid = split(/\./,$key);
259	    my $index_stp_if = pop(@decomp_oid);
260	    my $etat = $$hashref{$key};
261
262	    my $indexif = "1.3.6.1.2.1.17.1.4.1.2.$index_stp_if";
263
264	    &snmpmapOID("indexif","1.3.6.1.2.1.17.1.4.1.2.$index_stp_if");
265            my @desc_inter = &snmpget($param, "indexif");
266
267            &snmpmapOID("index","1.3.6.1.2.1.2.2.1.2.$desc_inter[0]");
268            my @nom_inter = &snmpget($param, "index");
269
270	    print FICH "Vlan$vlan $nom_inter[0]";
271
272	    my $nom_etat;
273	    if($etat == 1)
274	    {
275		print FICH "\tdisabled";
276		$nom_etat = "disabled";
277	    }
278	    elsif($etat == 2)
279	    {
280		print FICH "\tblocking";
281		$nom_etat = "blocking";
282	    }
283	    elsif($etat == 3)
284	    {
285		print FICH "\tlistening";
286		$nom_etat = "listening";
287	    }
288	    elsif($etat == 4)
289	    {
290		print FICH "\tlearning";
291		$nom_etat = "learning";
292	    }
293	    elsif($etat == 5)
294	    {
295		print FICH "\tforwarding";
296		$nom_etat = "forwarding";
297	    }
298	    elsif($etat == 6)
299	    {
300		print FICH "\tbroken";
301		$nom_etat = "broken";
302	    }
303	    if($index_stp_if == $rootPort)
304	    {
305		print FICH "\t-> root\n";
306		$stpInfos{"$host:$vlan:rootPort"} = $nom_inter[0];
307	    }
308	    else
309	    {
310		print FICH "\n";
311	    }
312	    $stpPorts{"$host:$vlan:$nom_inter[0]"} = $nom_etat;
313	}
314	close (FICH);
315
316	if($compteur == 0)
317	{
318	    #print "WARNING : $host, $vlan : aucun port actif dans l'instance de STP\n";
319	}
320    }
321    else
322    {
323	#print "ERROR: get_stp_catalyst($host,$community) : etat des ports du STP, pas de reponse\n";
324    }
325}
326
327
328
329sub compare_stp_state
330{
331    my ($key,$key2);
332    open(FICH,">$config{'dir_res_stp'}/stp.output.tmp");
333
334    foreach $key (keys %stpInfos)
335    {
336	if($key=~/(.*):(.*):bridgeId/)
337	{
338	    print FICH "\n";
339	    print FICH "$1:$2:bridgeId = $stpInfos{\"$1:$2:bridgeId\"}\n";
340	    print FICH "$1:$2:rootBridgeId = $stpInfos{\"$1:$2:rootBridgeId\"}($BridgeID{$stpInfos{\"$1:$2:rootBridgeId\"}})\n";
341	    if(defined($stpInfos{"$1:$2:rootPort"}))
342	    {
343		print FICH "$1:$2:rootPort = $stpInfos{\"$1:$2:rootPort\"}\n";
344	    }
345	    else
346	    {
347		print FICH "$1:$2:bridgeId = AUCUN\n";
348	    }
349
350	    my $host = $1;
351	    my $vlan = $2;
352	    foreach $key2 (keys %stpPorts)
353	    {
354		if($key2=~/$host:$vlan:(.*)/)
355		{
356		    print FICH "$host:$vlan:$1 = $stpPorts{\"$host:$vlan:$1\"}\n";
357		}
358	    }
359	}
360    }
361    close(FICH);
362
363    system("sort -t: +1n +0d $config{'dir_res_stp'}/stp.output > $config{'dir_res_stp'}/stp.output.sorted");
364    system("sort -t: +1n +0d $config{'dir_res_stp'}/stp.output.tmp > $config{'dir_res_stp'}/stp.output.tmp.sorted");
365
366    my $message = "Alertes Spanning Tree\n\n";
367    my $res = `diff -u $config{'dir_res_stp'}/stp.output.sorted $config{'dir_res_stp'}/stp.output.tmp.sorted`;
368
369    if($res ne "")
370    {
371	$message = "$message $res";
372	#print "$message";
373	#system("echo \"$message\" | mail -s \"[AUTO] Spanning Tree Topo changes\" seb\@crc.u-strasbg.fr");
374	system("mv $config{'dir_res_stp'}/stp.output.tmp $config{'dir_res_stp'}/stp.output");
375    }
376}
377
378
379return 1;
380
381
382
383