Source for file Switch_SNMP.php
Documentation is available at
Switch_SNMP.php
<?php
/**
* Switch_SNMP.php
*
* PHP version 5
*
* LICENSE: This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation.
*
*
@package
FreeNAC
*
@author
Hector Ortiz (FreeNAC Core Team)
*
@copyright
2007 FreeNAC
*
@license
http://www.gnu.org/copyleft/gpl.html GNU Public License Version 2
*
@version
SVN: $Id$
*
@link
http://www.freenac.net
*/
/**
* This class is intended to perform SNMP queries to all kind of switches.
* This class extends the
{@link Common}
class.
*/
class
Switch_SNMP
extends
Common
{
private
$props
=
array
(
)
;
/**
* Get an OID which returns only a single value, in other words, use this method when you're expecting a single value, not an array
*
@param
mixed
$community
SNMP community to use
*
@param
mixed
$oid
OID to query for
*
@return
mixed
The value of the OID
*/
private
function
getSingleOID
(
$community
,
$oid
)
{
## Continue if there is a valid ip and host is not down
if
(
$this
->
switch_ip
&&
!
$this
->
host_down
)
{
## This test is to avoid performing SNMP queries on hosts which are not responsive
if
((
!
$this
->
description
)
&&
(
strcmp
(
$oid
,
'1.3.6.1.2.1.1.1'
)
==
0
))
{
## Try to get the description. This OID should be available on all switches.
## Try 3 times before declaring switch dead
for
(
$i
=
0
;
$i
<
3
;
$i
++
)
{
$temp
=
@
snmprealwalk
(
$this
->
switch_ip
,
$community
,
$oid
)
;
if
(
$temp
)
$i
=
4
;
}
if
(
!
$temp
)
{
## We have tried 3 times and we didn't receive a response
$this
->
logger
->
logit
(
"
No response from {
$this
->
switch_ip
}
. Host seems to be down. If it is up, check your SNMP community.
"
)
;
## so mark host as down
$this
->
props
[
'host_down'
]
=
true
;
return
false
;
}
}
else
{
## We already have the description, which means that host is up, so get the OID we are interested in
$this
->
logger
->
debug
(
"
Retrieving OID
$oid
from switch {
$this
->
switch_ip
}
"
,
3
)
;
$temp
=
@
snmprealwalk
(
$this
->
switch_ip
,
$community
,
$oid
)
;
}
if
(
$temp
)
{
## There is information for the OID we asked for, clean it
$temp
=
array_map
(
"remove_type"
,
$temp
)
;
## And get the first value of the returned array
$temp
=
array_shift
(
$temp
)
;
return
$temp
;
}
else
{
## Apparently the host is up, but there is not information available, then this OID is not present on the queried device
$this
->
logger
->
debug
(
"
OID
$oid
is not present on switch {
$this
->
switch_ip
}
"
,
3
)
;
return
false
;
}
}
else
{
## Useless to continue if we don't have a valid IP or host is down
return
false
;
}
}
/**
* Get an OID which returns an array, in other words, use this method when you're expecting an array
* @param mixed $community SNMP community to use
* @param mixed $oid OID to query for
* @return mixed The value of the OID, false otherwise
*/
private
function
getArrayOID
(
$community
,
$oid
)
{
## Continue if there is a valid ip and host is not down
if
(
$this
->
switch_ip
&&
!
$this
->
host_down
)
{
## This test is to avoid performing SNMP queries on hosts which are not responsive
if
((
!
$this
->
description
)
&&
(
strcmp
(
$oid
,
'1.3.6.1.2.1.1.1'
)
==
0
))
{
## Try to get the description. This OID should be available on all switches.
## Try 3 times before declaring switch dead
for
(
$i
=
0
;
$i
<
3
;
$i
++
)
{
$temp
=
@
snmprealwalk
(
$this
->
switch_ip
,
$community
,
$oid
)
;
if
(
$temp
)
$i
=
4
;
}
if
(
!
$temp
)
{
## We have tried 3 times and we didn't receive a response
$this
->
logger
->
logit
(
"
No response from {
$this
->
switch_ip
}
. Host seems to be down. If it is up, check your SNMP community.
"
)
;
## so mark host as down
$this
->
props
[
'host_down'
]
=
true
;
return
false
;
}
}
else
{
## We already have the description, which means that host is up, so get the OID we are interested in
$this
->
logger
->
debug
(
"
Retrieving OID
$oid
from switch {
$this
->
switch_ip
}
"
,
3
)
;
$temp
=
@
snmprealwalk
(
$this
->
switch_ip
,
$community
,
$oid
)
;
}
if
(
$temp
)
{
## There is information for the OID we asked for, clean it and return the array
$temp
=
array_map
(
"remove_type"
,
$temp
)
;
return
$temp
;
}
else
{
## Apparently the host is up, but there is not information available, then this OID is not present on the queried device
$this
->
logger
->
debug
(
"
OID
$oid
is not present on switch {
$this
->
switch_ip
}
"
,
3
)
;
return
false
;
}
}
else
{
## Useless to continue if we don't have a valid IP or host is down
return
false
;
}
}
/**
* Get the first element of an array.
* @param array $array_var Array we want to manipulate
* @return mixed First value in the array, false otherwise
*/
private
function
getFirstFromArray
(
$array_var
)
{
if
(
is_array
(
$array_var
))
{
$temp_array
=
array
(
)
;
## Clean out empty values
foreach
(
$array_var
as
$record
)
{
if
(
$record
)
$temp_array
[
]
=
$record
;
}
$temp
=
array_shift
(
$temp_array
)
;
return
$temp
;
}
return
false
;
}
/**
* Get the list of physical interfaces on the switch
* @param mixed $community SNMP query to use
*/
private
function
pollInterfaces
(
$community
=
false
)
{
## If no community has been specified, use the one defined in etc/config.inc
if
(
!
$community
)
{
global
$snmp_ro
;
$community
=
$snmp_ro
;
}
## Query for this system description if we haven't yet done so
if
(
!
$this
->
description
)
$this
->
pollDescription
(
$community
)
;
## Don't continue if host has been marked as down
if
(
$this
->
host_down
)
return
false
;
## Textual name of the interfaces
$interfaces
=
$this
->
getArrayOID
(
$community
,
'1.3.6.1.2.1.31.1.1.1.1'
)
;
## Has the interface a physical connector?
$physical
=
$this
->
getArrayOID
(
$community
,
'1.3.6.1.2.1.31.1.1.1.17'
)
;
## Value of the instance of the ifIndex object
#$ports=$this->getArrayOID($community,'1.3.6.1.2.1.17.1.4.1.2');
$result
=
array
(
)
;
# Ports contains a list of ports which are in the switch
#if (! $ports || ! $interfaces || ! $physical)
if
(
!
$interfaces
||
!
$physical
)
return
false
;
foreach
(
$interfaces
as
$k
=>
$v
)
{
$if_index
=
get_last_index
(
$k
)
;
if
(
stristr
(
array_find_key
(
$if_index
,
$physical
,
'.'
,
1
)
,
'true'
))
{
#This is the last test, it means the interface is a physical one
$result
[
$k
]
=
$v
;
}
}
$this
->
props
[
'interfaces'
]
=
$result
;
}
/**
* Get the description of this switch
* @param mixed $community SNMP query to use
*/
private
function
pollDescription
(
$community
=
false
)
{
## If no community has been specified, use the one defined in etc/config.inc
if
(
!
$community
)
{
global
$snmp_ro
;
$community
=
$snmp_ro
;
}
## Query for this system description if we haven't yet done so
if
(
!
$this
->
description
)
{
## Textual description on the entity
$this
->
props
[
'description'
]
=
$this
->
getSingleOID
(
$community
,
'1.3.6.1.2.1.1.1'
)
;
}
}
/**
* Get the switch name
* @param mixed $community SNMP query to use
*/
private
function
pollName
(
$community
=
false
)
{
## If no community has been specified, use the one defined in etc/config.inc
if
(
!
$community
)
{
global
$snmp_ro
;
$community
=
$snmp_ro
;
}
## Query for this system description if we haven't yet done so
if
(
!
$this
->
description
)
$this
->
pollDescription
(
$community
)
;
## Don't continue if host has been marked as down
if
(
$this
->
host_down
)
return
false
;
## Query for this system name if we haven't yet done so
if
(
!
$this
->
name
)
{
## An administratively-assigned name for this managed node
$this
->
props
[
'name'
]
=
$this
->
getSingleOID
(
$community
,
'1.3.6.1.2.1.1.5'
)
;
}
}
/**
* Get the switch location defined in the switch
* @param mixed $community SNMP query to use
*/
private
function
pollLocation
(
$community
=
false
)
{
## If no community has been specified, use the one defined in etc/config.inc
if
(
!
$community
)
{
global
$snmp_ro
;
$community
=
$snmp_ro
;
}
## Query for this system description if we haven't yet done so
if
(
!
$this
->
description
)
$this
->
pollDescription
(
$community
)
;
## Don't continue if host has been marked as down
if
(
$this
->
host_down
)
return
false
;
## Query for this system's location if we haven't yet done so
if
(
!
$this
->
location
)
{
## The physical location of this node
$this
->
props
[
'location'
]
=
$this
->
getSingleOID
(
$community
,
'1.3.6.1.2.1.1.6'
)
;
}
}
/**
* Get the contact details defined in the switch
* @param mixed $community SNMP query to use
*/
private
function
pollContact
(
$community
=
false
)
{
## If no community has been specified, use the one defined in etc/config.inc
if
(
!
$community
)
{
global
$snmp_ro
;
$community
=
$snmp_ro
;
}
## Query for this system description if we haven't yet done so
if
(
!
$this
->
description
)
$this
->
pollDescription
(
$community
)
;
## Don't continue if host has been marked as down
if
(
$this
->
host_down
)
return
false
;
# Query for this system's contact information if we haven't yet done so
if
(
!
$this
->
contact
)
{
## The textual identification of the contact person for this managed node
$this
->
props
[
'contact'
]
=
$this
->
getSingleOID
(
$community
,
'1.3.6.1.2.1.1.4'
)
;
}
}
/**
* Get the serial number of this switch
* @param mixed $community SNMP query to use
*/
private
function
pollSerial_Number
(
$community
=
false
)
{
## If no community has been specified, use the one defined in etc/config.inc
if
(
!
$community
)
{
global
$snmp_ro
;
$community
=
$snmp_ro
;
}
## Query for this system description if we haven't yet done so
if
(
!
$this
->
description
)
$this
->
pollDescription
(
$community
)
;
## Don't continue if host has been marked as down
if
(
$this
->
host_down
)
return
false
;
## Query for this system's serial number if we haven't yet done so
if
(
!
$this
->
serial_number
)
{
## The vendor-specific serial number string for the physical entity
$this
->
props
[
'serial_number'
]
=
$this
->
getFirstFromArray
(
$this
->
getArrayOID
(
$community
,
'1.3.6.1.2.1.47.1.1.1.1.11'
))
;
}
}
/**
* Get the model of this switch
* @param mixed $community SNMP query to use
*/
private
function
pollModel
(
$community
=
false
)
{
## If no community has been specified, use the one defined in etc/config.inc
if
(
!
$community
)
{
global
$snmp_ro
;
$community
=
$snmp_ro
;
}
## Query for this system description if we haven't yet done so
if
(
!
$this
->
description
)
$this
->
pollDescription
(
$community
)
;
## Don't continue if host has been marked as down
if
(
$this
->
host_down
)
return
false
;
## Query for this system's model if we haven't yet done so
if
(
!
$this
->
model
)
{
## The vendor-specific model name identifier string associated with this physical component.
$this
->
props
[
'model'
]
=
$this
->
getFirstFromArray
(
$this
->
getArrayOID
(
$community
,
'1.3.6.1.2.1.47.1.1.1.1.13'
))
;
}
}
/**
* Get the hardware version of this switch
* @param mixed $community SNMP query to use
*/
private
function
pollHardware
(
$community
=
false
)
{
## If no community has been specified, use the one defined in etc/config.inc
if
(
!
$community
)
{
global
$snmp_ro
;
$community
=
$snmp_ro
;
}
## Query for this system description if we haven't yet done so
if
(
!
$this
->
description
)
$this
->
pollDescription
(
$community
)
;
## Don't continue if host has been marked as down
if
(
$this
->
host_down
)
return
false
;
## Query for this system's hardware version if we haven't yet done so
if
(
!
$this
->
hardware
)
{
## Vendor-specific hardware revision
$this
->
props
[
'hardware'
]
=
$this
->
getFirstFromArray
(
$this
->
getArrayOID
(
$community
,
'1.3.6.1.2.1.47.1.1.1.1.8'
))
;
}
}
/**
* Get the interface descriptions
* @param mixed $community SNMP query to use
*/
private
function
pollInterface_Descriptions
(
$community
=
false
)
{
## If no community has been specified, use the one defined in etc/config.inc
if
(
!
$community
)
{
global
$snmp_ro
;
$community
=
$snmp_ro
;
}
## Query for this system description if we haven't yet done so
if
(
!
$this
->
description
)
$this
->
pollDescription
(
$community
)
;
## Don't continue if host has been marked as down
if
(
$this
->
host_down
)
return
false
;
## Query for this system's interface descriptions if we haven't yet done so
if
(
!
$this
->
interface_descriptions
)
{
## Alias name for an interface, as defined by a network manager
$this
->
props
[
'interface_descriptions'
]
=
$this
->
getArrayOID
(
$community
,
'1.3.6.1.2.1.31.1.1.1.18'
)
;
}
}
/**
* Get the firmware version of this switch
* @param mixed $community SNMP query to use
*/
private
function
pollFirmware
(
$community
=
false
)
{
## If no community has been specified, use the one defined in etc/config.inc
if
(
!
$community
)
{
global
$snmp_ro
;
$community
=
$snmp_ro
;
}
## Query for this system description if we haven't yet done so
if
(
!
$this
->
description
)
$this
->
pollDescription
(
$community
)
;
## Don't continue if host has been marked as down
if
(
$this
->
host_down
)
return
false
;
## Query for this system's firmware version if we haven't yet done so
if
(
!
$this
->
firmware
)
{
## Vendor-specific firmware revision
$this
->
props
[
'firmware'
]
=
$this
->
getFirstFromArray
(
$this
->
getArrayOID
(
$community
,
'1.3.6.1.2.1.47.1.1.1.1.9'
))
;
}
}
/**
* Get the software version present on this switch
* @param mixed $community SNMP query to use
*/
private
function
pollSoftware
(
$community
=
false
)
{
## If no community has been specified, use the one defined in etc/config.inc
if
(
!
$community
)
{
global
$snmp_ro
;
$community
=
$snmp_ro
;
}
## Query for this system description if we haven't yet done so
if
(
!
$this
->
description
)
$this
->
pollDescription
(
$community
)
;
## Don't continue if host has been marked as down
if
(
$this
->
host_down
)
return
false
;
## Query for this system's software version if we haven't yet done so
if
(
!
$this
->
software
)
{
## Vendor-specific software revision
$this
->
props
[
'software'
]
=
$this
->
getFirstFromArray
(
$this
->
getArrayOID
(
$community
,
'1.3.6.1.2.1.47.1.1.1.1.10'
))
;
}
}
/**
* Initialize the Switch_SNMP object
* @param mixed $ip IP address of the switch
*/
public
function
__construct
(
$ip
)
{
parent
::
__construct
(
)
;
## Check if there is SNMP support
if
(
!
defined
(
'SNMP_NULL'
))
{
$this
->
logger
->
logit
(
"Your installation of PHP lacks support for SNMP"
,
LOG_ERR
)
;
$this
->
props
[
'host_down'
]
=
true
;
}
else
{
## There is SNMP support, validate IP address
$valid
=
true
;
$tmp
=
explode
(
"."
,
$ip
)
;
if
(
count
(
$tmp
)
<
4
)
{
$valid
=
false
;
}
else
{
foreach
(
$tmp
AS
$sub
)
{