source: ocsinventory-agent/trunk/fuentes/lib/Ocsinventory/Agent/Modules/Snmp.pm @ 468

Last change on this file since 468 was 468, checked in by mabarracus, 4 years ago

Copyt trusty code

File size: 12.0 KB
Line 
1###############################################################################
2## OCSINVENTORY-NG
3## Copyleft Guillaume PROTET 2010
4## Web : http://www.ocsinventory-ng.org
5##
6## This code is open source and may be copied and modified as long as the source
7## code is always made freely available.
8## Please refer to the General Public Licence http://www.gnu.org/ or Licence.txt
9################################################################################
10
11package Ocsinventory::Agent::Modules::Snmp;
12
13use strict;
14no strict 'refs';
15use warnings;
16
17use XML::Simple;
18use Digest::MD5;
19
20sub new {
21   my $name="snmp";   #Set the name of your module here
22
23   my (undef,$context) = @_;
24   my $self = {};
25
26
27   #Create a special logger for the module
28   $self->{logger} = new Ocsinventory::Logger ({
29            config => $context->{config}
30   });
31   $self->{logger}->{header}="[$name]";
32
33   $self->{common} = $context->{common};
34
35   $self->{context}=$context;
36
37   $self->{structure}= {
38                        name => $name,
39                        start_handler => $name."_start_handler", 
40                        prolog_writer => undef,     
41                        prolog_reader => $name."_prolog_reader", 
42                        inventory_handler => undef,
43                        end_handler => $name."_end_handler",
44   };
45
46   $self->{number_scan}=0;
47   $self->{snmp_oid_run}=$name."_oid_run";
48   $self->{func_oid}={};
49   $self->{snmp_dir}=[];
50
51   my $spec_dir_snmp="Ocsinventory/Agent/Modules/Snmp/";
52   $self->{spec_dir_snmp}=$spec_dir_snmp;
53   $self->{spec_module_snmp}="Ocsinventory::Agent::Modules::Snmp::";
54
55   # We are going to search where is the directory Ocsinventory/Modules/snmp
56   foreach my $dir ( @INC ) {
57      my $res_dir=$dir."/".$spec_dir_snmp;
58      if ( -d $res_dir ) {
59        push(@{$self->{snmp_dir}},$res_dir);
60      }
61   }
62
63   #We create a xml for the snmp inventory that we will be sent to server
64   $self->{inventory}={};
65
66   bless $self;
67}
68
69
70sub snmp_start_handler {       
71   my $self = shift;
72   my $logger = $self->{logger};
73   my $common = $self->{context}->{common};
74   my $config = $self->{context}->{config};
75   
76   $logger->debug("Calling snmp_start_handler");
77
78   #Disabling module if local mode
79   if ($config->{stdout} || $config->{local}) {
80     $self->{disabled} = 1;
81     $logger->info("Agent is running in local mode...disabling module");
82   }
83
84   #If we cannot load prerequisite, we disable the module
85   unless ($common->can_load('Net::SNMP')) { 
86     $self->{disabled} = 1;
87     $logger->error("Net::SNMP perl module is missing !!");
88     $logger->error("Humm my prerequisites are not OK...disabling module :( :(");
89   }
90}
91
92
93sub snmp_prolog_reader {
94   my ($self, $prolog) = @_;
95   my $logger = $self->{logger};
96   my $network = $self->{context}->{network};
97
98   my $option;
99
100   $logger->debug("Calling snmp_prolog_reader");
101   
102   $prolog      = XML::Simple::XMLin( $prolog, ForceArray => ['OPTION', 'PARAM']);
103
104   for $option (@{$prolog->{OPTION}}){
105      if( $option->{NAME} =~/snmp/i){
106         $self->{doscans} = 1 ;
107         for ( @{ $option->{PARAM} } ) {
108
109            if($_->{'TYPE'} eq 'DEVICE'){
110              #Adding the IP in the devices array
111              push @{$self->{netdevices}},{
112                IPADDR => $_->{IPADDR},
113                MACADDR => $_->{MACADDR},
114              };
115            }
116
117            if($_->{'TYPE'} eq 'COMMUNITY'){
118              #Adding the community in the communities array
119              push @{$self->{communities}},{
120                VERSION=>$_->{VERSION},
121                NAME=>$_->{NAME},
122                USERNAME=>$_->{USERNAME},
123                AUTHKEY=>$_->{AUTHKEY},
124                AUTHPASSWD=>$_->{AUTHPASSWD},
125              };
126            }
127         }
128      }
129   }
130}
131
132
133sub snmp_end_handler {
134   my $self = shift;
135   my $logger = $self->{logger};
136   my $common = $self->{context}->{common};
137   my $network = $self->{context}->{network};
138
139   $logger->debug("Calling snmp_end_handler");
140
141   #If no order form server
142   return unless $self->{doscans};
143
144   #Flushing xmltags if it has not been done
145   $common->flushXMLTags();
146
147   #We get the config
148   my $config = $self->{context}->{config};
149   
150   
151   my $ip=$self->{netdevices};
152   my $communities=$self->{communities};
153   if ( ! defined ($communities ) ) {
154      $logger->debug("We have no Community from server, we use default public community");
155      $communities=[{VERSION=>"2",NAME=>"public"}];
156   }
157
158   my ($name,$comm,$error,$system_oid);
159
160   # sysName.0
161   my $snmp_sysname="1.3.6.1.2.1.1.5.0";
162   # sysDescr.0
163   my $snmp_sysdescr="1.3.6.1.2.1.1.1.0";
164   # sysLocation.0
165   my $snmp_syslocation="1.3.6.1.2.1.1.6.0";
166   # sysUpTime.0
167   my $snmp_sysuptime="1.3.6.1.2.1.1.3.0"; 
168   # sysObjectId.0
169   my $snmp_sysobjectid="1.3.6.1.2.1.1.2.0";
170   # syscontact.0
171   my $snmp_syscontact="1.3.6.1.2.1.1.4.0";
172
173
174
175   # Initalising the XML properties
176   my $snmp_inventory = $self->{inventory};
177   $snmp_inventory->{xmlroot}->{QUERY} = ['SNMP'];
178   $snmp_inventory->{xmlroot}->{DEVICEID} = [$self->{context}->{config}->{deviceid}];
179
180   # Begin scanning ip tables
181   foreach my $device ( @$ip ) {
182      my $session;
183      my $devicedata = $common->{xmltags};     #To fill the xml informations for this device
184
185      $logger->debug("Scanning $device->{IPADDR} device");     
186      # Search for the good snmp community in the table community
187      LIST_SNMP: foreach $comm ( @$communities ) {
188
189          # Test if we use SNMP v3
190          if ( $comm->{VERSION} eq "3"  ) {
191            ($session, $error) = Net::SNMP->session(
192                -retries     => 1 ,
193                -timeout     => 3,
194                -version     => 'snmpv'.$comm->{VERSION},
195                -hostname    => $device->{IPADDR},
196                # -community   => $comm->{NAME},
197                -translate   => [-nosuchinstance => 0, -nosuchobject => 0],
198                -username      => $comm->{USER},
199                -authpassword  => $comm->{AUTHPASSWD},
200                -authprotocol  => $comm->{AUTHPROTO},
201                -privpassword  => $comm->{PRIVPASSWD},
202                -privprotocol  => $comm->{PRIVPROTO},
203             );
204          } else {
205            # We have an older version v2c ou v1
206            ($session, $error) = Net::SNMP->session(
207                -retries     => 1 ,
208                -timeout     => 3,
209                -version     => 'snmpv'.$comm->{VERSION},
210                -hostname    => $device->{IPADDR},
211                          -community   => $comm->{NAME},
212                -translate   => [-nosuchinstance => 0, -nosuchobject => 0],
213             );
214          };
215          unless (defined($session)) {
216             $logger->error("Snmp ERROR: $error");
217          } else {
218                  $self->{snmp_session}=$session;
219
220             $self->{snmp_community}=$comm->{NAME}; #For a use in constructor module (Cisco)
221             $self->{snmp_version}=$comm->{VERSION};
222
223             $name=$session->get_request( -varbindlist => [$snmp_sysname] );
224             last LIST_SNMP if ( defined $name);
225             $session->close;
226                  $self->{snmp_session}=undef;
227          }
228      }
229               
230      if ( defined $self->{snmp_session} ) { 
231        # We have found the good Community, we can scan this equipment
232        my ($constr_oid,$full_oid,$device_name,$description,$location,$contact,$uptime,$domain,$macaddr);
233
234        # We indicate that we scan a new equipment
235        $self->{number_scan}++;
236
237        my $result;
238
239
240        $result=$session->get_request( -varbindlist => [$snmp_sysname]);
241        $device_name=$result->{$snmp_sysname}; 
242
243        $result=$session->get_request(-varbindlist => [$snmp_sysobjectid]);
244        $full_oid=$result->{$snmp_sysobjectid}; 
245
246        $result=$session->get_request(-varbindlist => [$snmp_sysdescr]);
247        $description=$result->{$snmp_sysdescr};
248
249        $result=$session->get_request(-varbindlist => [$snmp_syslocation]);
250        $location=$result->{$snmp_syslocation};
251       
252        $result=$session->get_request(-varbindlist => [$snmp_sysuptime]);
253        $uptime=$result->{$snmp_sysuptime};
254
255        $result=$session->get_request(-varbindlist => [$snmp_syscontact]);
256        $contact=$result->{$snmp_syscontact};
257
258        if ( $full_oid  =~ /1\.3\.6\.1\.4\.1\.(\d+)/ ) {
259            $system_oid=$1;
260        }
261
262        # We run the special treatments for the OID vendor
263        if ( $self->{snmp_oid_run}($self,$system_oid) == 1 ) {
264           # We have no vendor oid for this equipment
265           # we use default.pm
266           $self->{snmp_oid_run}($self,"Default");
267        }
268
269        $session->close;
270        $self->{snmp_session}=undef;
271
272        $macaddr = $device->{MACADDR};
273
274        #Create SnmpDeviceID
275        my $md5 = Digest::MD5->new;
276        $md5->add($macaddr, $system_oid);
277        my $snmpdeviceid = $md5->hexdigest;
278
279        #Adding standard informations
280        $common->setSnmpCommons({ 
281          IPADDR => $device->{IPADDR},
282          MACADDR => $macaddr,
283          SNMPDEVICEID => $snmpdeviceid,
284          NAME => $device_name,
285          DESCRIPTION => $description,
286          CONTACT => $contact,
287          LOCATION => $location,
288          UPTIME => $uptime,
289          WORKGROUP => $domain,
290        });
291
292        #Add all the informations in the xml for this device
293        push @{$snmp_inventory->{xmlroot}->{CONTENT}->{DEVICE}},$devicedata;
294      }
295
296      #We clear the xml data for this device
297      $common->flushXMLTags(); 
298   }
299 
300  $logger->info("No more SNMP device to scan"); 
301
302  #Formatting the XML and sendig it to the server
303  my $content = XMLout( $snmp_inventory->{xmlroot},  RootName => 'REQUEST' , XMLDecl => '<?xml version="1.0" encoding="UTF-8"?>', SuppressEmpty => undef );
304
305  #Cleaning XML to delete unprintable characters
306  my $clean_content = $common->cleanXml($content);
307
308  $network->sendXML({message => $clean_content});
309
310  $logger->debug("End snmp_end_handler :)");
311}
312
313
314sub snmp_oid_run {
315    my ($self,$system_oid)=@_;
316
317    my $logger=$self->{logger};
318    my $session=$self->{snmp_session};
319    my $spec_module_snmp=$self->{spec_module_snmp};
320
321   unless ( defined ( $self->{func_oid}{$system_oid} )) {
322      my $spec_dir_snmp=$self->{spec_dir_snmp};
323
324      # We init the default value
325      $self->{func_oid}{$system_oid}={};
326      $self->{func_oid}{$system_oid}{active}=0;
327      $self->{func_oid}{$system_oid}{oid_value}="1.3.6.1.2.1.1.5.0";
328      $self->{func_oid}{$system_oid}{oid_name}="Undefined";
329
330
331      # Can we find it in the snmp directory
332      foreach my $dir ( @{$self->{snmp_dir}} ) {
333          if ( -r $dir.$system_oid.".pm" ) {
334             # We find the module
335             my $module_found=$spec_module_snmp.$system_oid;
336             eval "use $module_found";
337             if ($@) {
338                $logger->debug ("Failed to load $module_found: $@");
339             } else {
340                # We have execute it. We can get the function pointer on snmp_run
341                my $package=$module_found."::";
342                $self->{func_oid}{$system_oid}{snmp_run}=$package->{'snmp_run'};
343                if ( defined ( $package->{'snmp_info'} ) ) {
344                   my $return_info=&{$package->{'snmp_info'}};
345                   if ( defined $return_info->{oid_value} ) {
346                      $self->{func_oid}{$system_oid}{oid_value}=$return_info->{oid_value};
347                   }
348                   if ( defined $return_info->{oid_name} ) {
349                      $self->{func_oid}{$system_oid}{oid_name}=$return_info->{oid_name};
350                   }
351                }
352
353                $self->{func_oid}{$system_oid}{active}=1;
354                 $self->{func_oid}{$system_oid}{last_exec}=0;
355             }
356          }
357      }
358   }
359
360   if ( $self->{func_oid}{$system_oid}{active} == 1 && $self->{func_oid}{$system_oid}{last_exec} < $self->{number_scan} )
361   { # we test that this function as never been executed for this equipment
362      # We test first that this OID exist for this equipment
363      my $oid_scan=$self->{func_oid}{$system_oid}{oid_value};
364      my $result=$session->get_request(-varbindlist => [ $oid_scan ] );
365
366      $self->{func_oid}{$system_oid}{last_exec}=$self->{number_scan};
367      if ( length ($result->{$oid_scan}) != 0 ) {
368         # This OID exist, we can execute it
369         #$logger->debug("Launching $system_oid\n");
370         &{$self->{func_oid}{$system_oid}{snmp_run}}($session,$self);
371      }
372   # We indicate that this equipment is the last scanned
373   } else {
374      return 1;
375   }
376   return 0;
377
378}
379
380
3811;
Note: See TracBrowser for help on using the repository browser.