# exported
use vars qw{
$PSTAT_SERVICE_REQ
$PSTAT_OFFLINE
$PSTAT_PAPER_JAM
$PSTAT_DOOR_OPEN
$PSTAT_TONER_OUT
$PSTAT_TONER_LOW
$PSTAT_PAPER_OUT
$PSTAT_PAPER_LOW
$PSTAT_IDLE
$PSTAT_PRINTING
$PSTAT_WARMING_UP
$PSTAT_UNREACHABLE
$PSTAT_MAX
};
# non-exported but global to the package:
use vars qw{
%statmsg
%prtstatmsg
%encoded_oids
$PAGECOUNT_OID
$MODEL_OID
$DEVICE_STATUS_OID
$PRINTER_STATUS_OID
$ERROR_STATE_OID
$MEMORY_SIZE_OID
$LEX_MODEL_OID
$LEX_CONSOLE_OID
$LEX_OPTRA_SERIAL_NO_OID
$LEX_INT_SERIAL_NO_OID
$HP_SERIAL_NO_OID
$HP_5M_SERIAL_NO_OID
};
# Loads modules from source directory if executed in source directory
use lib qw(. /usr/local/netprint/lib);
use npparams;
use SNMP_Session;
use BER;
#### Global data
BEGIN {
# OIDs for SNMP variables
# Techniques for figuring out OIDs:
# To get OID for printer serial number:
# snmpwalk uris1 public .iso.3.6.1 | grep 11CKWB3
# To access an OID:
# snmpget uris1 public .1.3.6.1.4.1.641.2.1.2.1.6.1
# Helpful URL: www.ibr.cs.tu-bs.de/cgi-bin/sbrowser.cgi
# OIDs common to all printers (I hope)
$PAGECOUNT_OID = '1.3.6.1.2.1.43.10.2.1.4.1.1'; # prtMarkerLifeCount.1.1
$MODEL_OID = '1.3.6.1.2.1.25.3.2.1.3.1'; # hrDeviceDescr.1
$DEVICE_STATUS_OID = '1.3.6.1.2.1.25.3.2.1.5.1'; # hrDeviceStatus.1
$PRINTER_STATUS_OID= '1.3.6.1.2.1.25.3.5.1.1.1'; # hrPrinterStatus.1
$ERROR_STATE_OID = '1.3.6.1.2.1.25.3.5.1.2.1'; # hrPrinterDetectedErrorState.1
$MEMORY_SIZE_OID = '1.3.6.1.2.1.25.2.2.0'; # hrMemorySize.0
# Manufacturer or model-specific OIDs
$LEX_MODEL_OID = '1.3.6.1.4.1.641.2.1.2.1.2.1'; # prtgenPrinterName.1
$LEX_CONSOLE_OID = '1.3.6.1.2.1.43.16.5.1.2.1.1'; # prtConsoleDisplayBufferText.1.1
$LEX_OPTRA_SERIAL_NO_OID = '1.3.6.1.4.1.641.2.1.2.1.6.1'; # Not in published Lexmark MIB
$LEX_INT_SERIAL_NO_OID = '1.3.6.1.4.1.641.2.1.2.1.5.1'; # Bogus (not available)
$HP_SERIAL_NO_OID = '1.3.6.1.2.1.43.5.1.1.17.1', # Not in published RFC1759
$HP_5M_SERIAL_NO_OID= '1.3.6.1.4.1.11.2.3.9.4.2.1.1.3.3.0', # HP private MIB
# Note: The bit definitions for the first 8 of the items below are taken
# from the description of the values for hrPrinterDetectedErrorState in
# RFC1759.
$PSTAT_SERVICE_REQ = 1;
$PSTAT_OFFLINE = 2;
$PSTAT_PAPER_JAM = 4;
$PSTAT_DOOR_OPEN = 8;
$PSTAT_TONER_OUT = 16;
$PSTAT_TONER_LOW = 32;
$PSTAT_PAPER_OUT = 64;
$PSTAT_PAPER_LOW = 128;
$PSTAT_IDLE = 256;
$PSTAT_PRINTING = 512;
$PSTAT_WARMING_UP = 1024;
$PSTAT_UNREACHABLE = 2048;
$PSTAT_MAX = 2048;
########################################################
# get_status($ip)
#
# $ip IP address or DNS name of printer
# $model Printer model or undef
# Returns:
# $status Bit encoded printer status
# Uses SNMP to find the status and returns an errorcode
# which can be deciphered in err2str, which will return an array of
# strings specifying the error(s) occuring.
sub get_status {
my($ip, $model) = @_;
# No idea what this is about
# if ( $ip eq '' ) {
# return( { 'status' => $PSTAT_IDLE } );
# }
my($community) = 'public';
# The following line can be commented out for debugging purposes.
$SNMP_Session::suppress_warnings = 1;
my($session);
if ( ! ($session = SNMP_Session->open ($ip, $community, 161)) ) {
warn "Couldn't open SNMP session to $ip: $SNMP_Session::errmsg";
return($PSTAT_UNREACHABLE);
}
$session->set_retries(2);
# Get printer model if necessary
if ( ! defined($model) ) {
$model = snmp_get_model($session);
}
if ( ! defined($model) ) {
return($PSTAT_UNREACHABLE);
}
my($error, $prtstatus, $console);
if ( $model =~ /^Lexmark/ ) {
# Lexmark printers require looking at the console status too because
# printer_status doesn't show 'printing' until the paper starts moving.
($error, $prtstatus, $console) = snmp_get($session, $ERROR_STATE_OID, $PRINTER_STATUS_OID, $LEX_CONSOLE_OID);
$error = unpack("C", $error);
if ( ! defined($error) ) {
return($PSTAT_UNREACHABLE);
}
if ( $console =~ /Ready|Power Saver/ ) {
if ( defined($prtstatmsg{$prtstatus}) ) {
$error |= $prtstatmsg{$prtstatus};
}
}
else {
$error |= $PSTAT_PRINTING;
}
}
elsif ( $model =~ /^HP/ ) {
########################################################
# get_snmp_info($ip)
#
# $ip IP address or DNS name of printer
# $model Printer model or undef
# Returns:
# $snmpinfo Hash reference containing keys 'pagecount', 'model', 'status',
# 'device_status', 'printer_status', 'error_state',
# 'memory_size', 'serial_no', 'status', 'real_model'.
sub get_snmp_info {
my($ip, $model) = @_;
# No idea what this is about
# if ( $ip eq '' ) {
# return( { 'status' => $PSTAT_IDLE } );
# }
my($community) = 'public';
# The following line can be commented out for debugging purposes.
$SNMP_Session::suppress_warnings = 1;
my($session);
if ( ! ($session = SNMP_Session->open ($ip, $community, 161)) ) {
warn "Couldn't open SNMP session to $ip: $SNMP_Session::errmsg";
return( { 'status' => $PSTAT_UNREACHABLE } );
}
$session->set_retries(2);
# Get printer model if necessary
if ( ! defined($model) ) {
$model = snmp_get_model($session);
}
if ( ! defined($model) ) {
return( { 'status' => $PSTAT_UNREACHABLE } );
}
#########################################################
# err2str ($code)
#
# Given an errorcode, this sub will convert the
# code to an array of strings, each ending in a newline.
#########################################################
# printer_ok($code)
#
# Given a printer status code, return TRUE for printer OK, and FALSE
# for printer not functioning.
#########################################################
# printer_idle($code)
#
# Given a printer status code, return TRUE for printer idle, and FALSE
# for any other printer status.
sub printer_idle {
my($code) = @_;
return( (($code & $PSTAT_IDLE) != 0) and printer_ok($code) );
}
#########################################################
# Get printer page count
#
# $ip Printer IP address or DNS name
# Returns:
# $pagecount Printer page count or -1 if error
sub get_pagecount {
my($ip) = @_;
# The following line can be commented out for debugging purposes.
$SNMP_Session::suppress_warnings = 1;
my($session);
unless ( $session = SNMP_Session->open($ip, 'public', 161) ) {
return(-1);
}
my(@snmpvals) = snmp_get($session, $PAGECOUNT_OID);
$session->close();
unless ( $#snmpvals >= 0 ) {
return(-1); # Will come here if 'noSuchName' error!!
}
return($snmpvals[0]);
}
#########################################################
# Get printer model using SNMP
#
# $session SNMP session ID
# Returns:
# $model Printer model or undef if error
sub snmp_get_model {
my($session) = @_;
my($model);
if ( ! (($model) = snmp_get($session, $MODEL_OID)) ) {
return(undef);
}
return(undef) if ! defined($model);
$model =~ s/\s+$//;
return($model);
}
#########################################################
# Query the SNMP agent
#
# $session SNMP session ID
# @oids Array of OIDs
# Returns:
# @values Array of values or undef if error
# Given a session ID and an array of variable nicknames, query the SNMP
# agent and return an array of values. We are assuming that the values
# come back in the same order as the OIDs.
sub snmp_get {
my($session, @oids) = @_;