#include <stdio.h>
#include <assert.h>
#include <string.h>
#include "argflags.h"
#include "npaconsts.h"
#include "npastructs.h"
#include "npaoids.h"
#include "structfill.h"
#include "compat.h"
#define MAXSTR 1024
#define ERR_NO_RESPONSE 8
#define ERR_SOCK_ERROR 9
#define ERR_NOT_PRINTER 10
#define ERR_UNKNOWN_DEVICE 11
extern char *progname;
ConnectionInfo DUMMY_CONNINFO;
HrStorageTable BHSID;
static const char HPSTR[]="JETDIRECT";
static const char LEXMARKSTR[]="Lexmark";
static const char TEKTRONIXSTR[]="Tektronix";
static const char XEROXDC230STR[]="131;C1H011131;";
static const char XEROXDC230STR2[]=";C1H017730;";
static const char XEROXDC265STR[]="3UP060485";
static const char XEROXSTR[]="Xerox";
static const char QMSSTR[]="QMS";
static const char IBMSTR[]="IBM";
static const char EFISTR[]="EFI Fiery Color Printer Server";
static const char EFISTR2[]="EFI Fiery Server ZX";
static const char FUJISTR[]="Able Model-PRII";
static const char *TCPSTATES[]={NULL,"closed","listen","synSent",
"synReceived","established","finWait1",
"finWait2","closeWait","lastAck",
"closing","timeWait"};
static const char *HRSTATUSSTATES[]={NULL,"other","unknown","idle",
"printing","warmup"};
static const char *HPCFGSOURCESTATES[]={"bootp","manual","unknown",
"manual","bootp","dhcp"};
void handle_unrecoverable(char *progname,char *hostname,
SNMP_error_unrecoverable &error){
char errnum=0;
switch(error){
case SNMPERR_NoResponse:
fprintf(stderr,"%s: No response from %s\n",progname,hostname);
errnum=ERR_NO_RESPONSE;
break;
case SNMPERR_SocketErr:
char buf[50];
snprintf(buf,50,"%s: %u.%u.%u.%u",progname,hostname);
perror(buf);
errnum=ERR_SOCK_ERROR;
break;
}
int *i=new int;
*i=errnum;
pthread_exit(i);
}
void usage(){
fprintf(stderr,"npadmin [-c community] {options} printername\n");
}
void not_sup(char *option,char* hostname){
fprintf(stderr,"%s: %s option not supported on this printer type.\n",
hostname,option);
}
char *decode_status(long stat){
char *buf=new char[256];
memset(buf,0,256);
if(stat&64) strcat(buf,"Transitioning ");
if(stat&32) strcat(buf,"Off-Line ");
if(stat&16) strcat(buf,"Critical Alerts ");
if(stat&8) strcat(buf,"Non-Critical Alerts ");
switch(stat&7){
case 0:
strcat(buf,"Available and Idle");
break;
case 2:
strcat(buf,"Available and Standby");
break;
case 4:
strcat(buf,"Available and Active");
break;
case 6:
strcat(buf,"Available and Busy");
break;
case 1:
strcat(buf,"Unavailable and OnRequest");
break;
case 3:
strcat(buf,"Unavailable because Broken");
break;
case 5:
strcat(buf,"Unknown");
break;
default:
assert(0); //undefined state
}
return buf;
}
/* XXX: This is an ugly evil nasty hack. Basically HP 4 series
printers and below do not support the hostmib or the printmib
but yet we still want to be able to get their current status
information as well as the information in the display and so we
need to get it out of the private mibs. This seems like the
right place to do it because it is before the hostmib
processing is run and after we know what kind of printer we
are dealing with. */
void do_hppriv_get(SNMP_session &session, unsigned long *argflags,
unsigned long &operflags){
SNMP_structFiller hpprivreq(session);
HPPrivInfo privinfo;
char buf[MAXSTR];
if(CK_STATUS_FLAG)
hpprivreq.append(HPNPSYSSTATUSMESSAGE,STRING_TAG,
(char*)&(privinfo.status)-(char*)&privinfo);
if(CK_DISPLAY_FLAG)
hpprivreq.append(HPNPGDSTATUSDISPLAY,STRING_TAG,
(char*)&(privinfo.frontpanel)-(char*)&privinfo);
try{
hpprivreq.get(&privinfo);
} catch (SNMP_error_unrecoverable &error){
handle_unrecoverable(progname, session.Hostname(),error);
}
/* reset the flags -- we got the message but we don't want it to
propegating down. */
if(CK_STATUS_FLAG){
RST_STATUS_FLAG;
if(!(CK_HOSTMIB_FLAGS))
operflags&=~NEED_HOSTMIB_FLAG;
snprintf(buf,MAXSTR,"status=\"%s\";",privinfo.status);
session.printstr(argflags,NEEDNL_ENTRY,buf);
}
if(CK_DISPLAY_FLAG){
RST_DISPLAY_FLAG;
if(!(CK_PRINTMIB_FLAGS))
operflags&=~NEED_PRINTMIB_FLAG;
snprintf(buf,MAXSTR,"displayBufferText=\"%s\";\n",privinfo.frontpanel);
session.printstr(argflags,NEEDNL_ENTRY,buf);
}
}
/* XXX: Another ugly evil nasty hack. */
void do_hppriv_set(SNMP_session &session, unsigned long *argflags,
unsigned long &operflags,char **optparam){
OidSeq hpprivsets;
if(CK_REBOOT_FLAG)
hpprivsets.append(HPREBOOT,INT_TAG,1);
if(CK_UPDATEFIRM_FLAG){
// fprintf(stderr,"debug: %s \n",optparam[UPDATEFIRM_PARAM]);
hpprivsets.append(HPICFDOWNLOADSTATUS,INT_TAG,4); // create and go
char prefix[]="1.3.6.1.6.1.1";
hpprivsets.append(HPICFDOWNLOADTDOMAIN,OID_TAG,prefix,13);
char *server,*filename;
// fprintf(stderr, "debug: %s \n",optparam[UPDATEFIRM_PARAM]);
server=strdup(optparam[UPDATEFIRM_PARAM]);
assert(server);
filename=strchr(server,':');
assert(filename);
*filename=0;
filename++;
struct hostent *he;
assert((he=gethostbyname(server))!=NULL);
char *svrip=strdup(he->h_addr);
assert(svrip!=NULL && (svrip=(char*)realloc(svrip,he->h_length+3)));
svrip[he->h_length]=0;
svrip[he->h_length+1]=0x45;
svrip[he->h_length+2]=0;
hpprivsets.append(HPICFDOWNLOADTADDRESS,STRING_TAG,svrip,he->h_length+2);
hpprivsets.append(HPICFDOWNLOADFILENAME,STRING_TAG,filename,
strlen(filename)+1);
free(server);
}
OidSeq *response=session.set(&hpprivsets);
RST_REBOOT_FLAG;
}
void do_general_get(SNMP_session &session, unsigned long *argflags,
unsigned long &operflags,char **optparam){
// setup the requests
SNMP_structFiller getreq(session);
GeneralPrinterInfo gpi;
if(CK_VENDOR_FLAG || CK_MODEL_FLAG || CK_HOSTMIB_FLAG || CK_PRINTMIB_FLAG ||
operflags&(NEED_HOSTMIB_FLAG | NEED_PRINTMIB_FLAG | NEED_VENDOR_FLAG))
getreq.append(SYSDESC,STRING_TAG,(char*)&gpi.sysDesc-(char*)&gpi);
//vendor done, model done for lexmarks
if(CK_CONTACT_FLAG){
getreq.append(SYSCONTACT,STRING_TAG,(char*)&gpi.sysContact-(char*)&gpi);
getreq.append(SYSLOCATION,STRING_TAG,(char*)&gpi.sysLocation-
(char*)&gpi);
// contact done
}
if(CK_NETCONFIG_FLAG){
getreq.append(IFPHYSICALADDRESS,STRING_TAG,(char*)&gpi.hwaddr-
(char*)&gpi);
getreq.append(IFTYPE,INT_TAG,(char*)&gpi.iftype-(char*)&gpi);
getreq.append(IPROUTENEXTHOP,IPADDR_TAG,(char*)&gpi.gateway-(char*)&gpi);
char maskbuf[50]; // should be big enough
char *connhost=session.ConnHost();
int len=snprintf(maskbuf,50,"%s.%u.%u.%u.%u",IPENTNETMASK_BASE,
((unsigned)connhost[0] & 0xff),
((unsigned)connhost[1] & 0xff),
((unsigned)connhost[2] & 0xff),
((unsigned)connhost[3] & 0xff));
getreq.append(maskbuf,IPADDR_TAG,(char*)&gpi.netmask-(char*)&gpi);
} // end of if(CK_NETCONFIG_FLAG)
/* all the oids that fit in one packet have been loaded send
the request */
char retry=0;
do{
try{
getreq.get(&gpi);
retry=0;
} catch(SNMP_error_unrecoverable &error){
handle_unrecoverable(progname, session.Hostname(),error);
} catch(SNMP_error_oid *error){
assert(retry<=2);
if(*error==NOCONSTCAST IPROUTENEXTHOP){
getreq.remove(IPROUTENEXTHOP);
retry++;
} else if(*error==SYSDESC){
fprintf(stderr,
"Warning: %s does not have a system.sysDescr.0 probably Windows NT. Skipping.\n",
session.Hostname());
int *i=new int;
assert(i!=NULL);
*i=-3;
pthread_exit(i);
} else if(*error==SYSCONTACT || *error==SYSLOCATION){
getreq.remove(SYSCONTACT);
getreq.remove(SYSLOCATION);
RST_CONTACT_FLAG;
fprintf(stderr,
"Warning: %s does't provide system.sys%s ignoring --contact.\n",
session.Hostname(),
*error==SYSCONTACT?"Contact":"Location");
retry++;
} else {
fprintf(stderr,"debug: Bad things from %s\n",session.Hostname());
assert(0);
}
}
}while(retry);
char buf[MAXSTR];
// print out netconfig info
if(CK_NETCONFIG_FLAG){
/* make sure that we have the right interface basically this
is a problem for the lexmarks because they have a psudo
interface at .1 */
if(gpi.iftype!=6){ // 6 just happens to be the # for ethernet
SNMP_structFiller ifreq(session);
ifreq.append(IFPHYSICALADDRESS_BASE,STRING_TAG,(char*)&gpi.hwaddr-
(char*)&gpi);
ifreq.append(IFTYPE_BASE,INT_TAG,(char*)&gpi.iftype-(char*)&gpi);
while(gpi.iftype!=6)
try{
if(ifreq.get_next(&gpi)==NULL){
fprintf(stderr,"Warning: %s doesn't appear to have an ethernet "
"interface. Can't detect hwaddr.\n",session.Hostname());
break;
}
} catch (SNMP_error_unrecoverable &error){
handle_unrecoverable(progname, session.Hostname(),error);
}
}
/* this line expects the ip addresses to always be 4 bytes. */
char *connhost=session.ConnHost();
snprintf(buf,MAXSTR,"ipaddr=\"%u.%u.%u.%u\";netmask=\"%u.%u.%u.%u\";",
((unsigned)connhost[0] & 0xff),((unsigned)connhost[1] & 0xff),
((unsigned)connhost[2] & 0xff),((unsigned)connhost[3] & 0xff),
((unsigned)gpi.netmask[0] & 0xff),
((unsigned)gpi.netmask[1] & 0xff),
((unsigned)gpi.netmask[2] & 0xff),
((unsigned)gpi.netmask[3] & 0xff));
session.printstr(argflags,NEEDNL_ENTRY,buf);
if(gpi.iftype==6){
snprintf(buf,MAXSTR,"hwaddr=\"%02x:%02x:%02x:%02x:%02x:%02x:\";",
((unsigned)gpi.hwaddr[0] & 0xff),
((unsigned)gpi.hwaddr[1] & 0xff),
((unsigned)gpi.hwaddr[2] & 0xff),
((unsigned)gpi.hwaddr[3] & 0xff),
((unsigned)gpi.hwaddr[4] & 0xff),
((unsigned)gpi.hwaddr[5] & 0xff));
session.printstr(argflags,NEEDNL_ENTRY,buf);
}
if(gpi.gateway!=NULL){
snprintf(buf,MAXSTR,"gateway=\"%u.%u.%u.%u\";",
((unsigned)gpi.gateway[0] & 0xff),
((unsigned)gpi.gateway[1] & 0xff),
((unsigned)gpi.gateway[2] & 0xff),
((unsigned)gpi.gateway[3] & 0xff));
session.printstr(argflags,NEEDNL_ENTRY,buf);
}else{
fprintf(stderr,
"Warning: %s did not report a default gateway.\n",
session.Hostname());
}
}
/* ------ model and vendor ---------------------------------- */
if(gpi.sysDesc){
if(strstr(gpi.sysDesc,HPSTR)){
operflags|=HP_VENDOR;
/* This could be located in down in the section where there
it is only executed if it is run on a 4 series printer
that doesn't support the host mib but I am having some
trouble with sets on the 5 series printers and so I think
that it will be better to put it up here for the time
being.*/
if(CK_REBOOT_FLAG || CK_UPDATEFIRM_FLAG)
do_hppriv_set(session,argflags,operflags,optparam);
if(CK_VENDOR_FLAG)
session.printstr(argflags,NEEDNL_ENTRY,"vendor=\"HP\";");
/* damn hp makes us go down to the private enterprises area
to find out the model. The new 5 series printers are a bit
easier but the 4 series don't support the host mib. */
if(CK_MODEL_FLAG || CK_HOSTMIB_FLAG || CK_PRINTMIB_FLAG ||
operflags&(NEED_HOSTMIB_FLAG | NEED_PRINTMIB_FLAG)){
OidSeq modelreq(1,HPINFO);
OidSeq *modelresp;
try{
//fputs("debug: getting modelstr\n",stderr);
modelresp=session.get(&modelreq);
} catch (SNMP_error_unrecoverable &error){
handle_unrecoverable(progname, session.Hostname(),error);
}
assert(modelresp);
BerBase *hpinfo=modelresp->value(HPINFO);
assert(hpinfo);
assert(hpinfo->type()==STRING_TAG);
char hpbuf[256];
char buf2[100];
char *begin;
((BerString*)hpinfo)->copy(hpbuf, 256);
if(((BerString*)hpinfo)->strlen()==0){
fprintf(stderr,"Warning: %s model not reported.\n",
session.Hostname());
if(CK_STATUS_FLAG || CK_DISPLAY_FLAG) {
do_hppriv_get(session,argflags,operflags);
}
} else {
if((begin=strstr(hpbuf, "MODEL:"))!=NULL){
begin+=6;
begin+=!strncmp(begin,"HP ",3)?3:0;
} else if((begin=strstr(hpbuf,"MDL:"))
!=NULL){
/* work around the fact that a 1600cm doesn't have
MODEL it has MDL */
begin+=4; //skip past "MDL:"
} else {
fprintf(stderr,
"%s: Can't find \"MODEL:\" or \"MDL:\" in \"%s\"\n",
session.Hostname(),hpbuf);
int *i=new int;
assert(i);
*i=-3;
pthread_exit(i);
}
char *end=strchr(begin,';');
if (end==NULL)
end=begin+strlen(begin);
strncpy(buf2,begin,end-begin);
buf2[end-begin]='\0';
if(CK_MODEL_FLAG){
snprintf(buf,MAXSTR,"model=\"%s\";",buf2);
session.printstr(argflags,NEEDNL_ENTRY,buf);
}
/* this line will probably have to be tweaked a bit I
basically believe all the HP printers except for the
5 series and the *000 series do not support the host
or printmib */
/* We need to come up with a better way to do this :-) */
if((strstr(buf2,"000") && !strstr(buf2,"2000")) ||
(strstr(buf2,"LaserJet 5") && !strstr(buf2,"Color") &&
!strstr(gpi.sysDesc,"JETDIRECT EX")) ||
strstr(buf2,"8100") || strstr(buf2, "4500") ||
strstr(buf2, "8500") || strstr(buf2, "4050")){
operflags|=HAS_PRINTMIB_FLAG;
// work around acient broken firmware
if(!strstr(gpi.sysDesc,"EEPROM A.03."))
operflags|=HAS_HOSTMIB_FLAG;
else
fprintf(stderr,
"Warning: %s has ancient firmware. Please upgrade it!\n",
session.Hostname());
} else {
if(CK_STATUS_FLAG || CK_DISPLAY_FLAG)
do_hppriv_get(session,argflags,operflags);
if (CK_LANGUAGES_FLAGS){
if((begin=strstr(hpbuf,
"COMMAND SET:"))!=NULL){
begin+=12;
} else if((begin=strstr(hpbuf,"CMD:"))
!=NULL){
begin+=4;
}
end=strchr(begin,';');
if (end==NULL)
end=begin+strlen(begin);
strncpy(buf2,begin,end-begin);
buf2[end-begin]='\0';
end=buf2-1;
do
{
begin=end+1;
end=strchr(begin, ',');
if (end)
*end='\0';
if(CK_POSTSCRIPT_FLAG && strcmp(begin, "POSTSCRIPT")==0) {
session.printstr(argflags,NEEDNL_ENTRY,"postscript=\"Y\";");
RST_POSTSCRIPT_FLAG;
}
if(CK_PCL_FLAG && strcmp(begin, "PCL")==0) {
session.printstr(argflags,NEEDNL_ENTRY,"pcl=\"Y\";");
RST_PCL_FLAG;
}
if(CK_HPGL_FLAG && strcmp(begin, "HP-GL")==0) {
session.printstr(argflags,NEEDNL_ENTRY,"hpgl=\"Y\";");
RST_HPGL_FLAG;
}
if(CK_PJL_FLAG && strcmp(begin, "PJL")==0) {
session.printstr(argflags,NEEDNL_ENTRY,"pjl=\"Y\";");
RST_PJL_FLAG;
}
} while(end);
}
}
}
delete modelresp;
}
} else if(!strncmp(gpi.sysDesc,LEXMARKSTR,7)){
operflags|=LEX_VENDOR;
operflags|=HAS_HOSTMIB_FLAG|HAS_PRINTMIB_FLAG;
if(CK_VENDOR_FLAG){
session.printstr(argflags,NEEDNL_ENTRY,"vendor=\"Lexmark\";");
}
if(CK_MODEL_FLAG){
char buf2[50];
char *begin=gpi.sysDesc+8;
/* this is a cool thing. On the lexmarks that I have
looked at they seperate the version and the model with
a double space. This makes parsing easier. */
int len=strstr(begin," ")-begin;
strncpy(buf2,begin,len);
buf2[len]=0;
snprintf(buf,MAXSTR,"model=\"%s\";",buf2);
session.printstr(argflags,NEEDNL_ENTRY,buf);
}
} else if(!strncmp(gpi.sysDesc,TEKTRONIXSTR,9)){
char tekbuf[256];
operflags|=HAS_HOSTMIB_FLAG|HAS_PRINTMIB_FLAG|TEK_VENDOR;
OidSeq modelreq(1,HRDEVICEDESC);
OidSeq *modelresp;
try{
modelresp=session.get(&modelreq);
} catch (SNMP_error_unrecoverable &error){
handle_unrecoverable(progname, session.Hostname(),error);
} catch(SNMP_error_oid *error){
char *connhost=session.ConnHost();
fprintf(stderr,
"Warning: Tektronix printer %s does not support the hostmib.\n",
session.Hostname());
operflags&=~(HAS_HOSTMIB_FLAG|HAS_PRINTMIB_FLAG);
modelreq.remove(HRDEVICEDESC);
modelreq.append(TKMODEL);
try{
modelresp=session.get(&modelreq);
} catch (SNMP_error_unrecoverable &error){
handle_unrecoverable(progname, session.Hostname(),error);
} catch (SNMP_error_oid *error){
assert(0);
}
if(CK_MODEL_FLAG){
RST_MODEL_FLAG;
BerBase *hrdevdesc=modelresp->value(TKMODEL);
assert(hrdevdesc->type()==STRING_TAG);
((BerString*)hrdevdesc)->copy(tekbuf, 256);
snprintf(buf,MAXSTR,"model=\"%s\";",tekbuf);
session.printstr(argflags,NEEDNL_ENTRY,buf);
delete modelresp;
}
}
if(CK_VENDOR_FLAG){
session.printstr(argflags,NEEDNL_ENTRY,"vendor=\"Tektronix\";");
}
if(CK_MODEL_FLAG){
assert(modelresp);
BerBase *hrdevdesc=modelresp->value(HRDEVICEDESC);
assert(hrdevdesc->type()==STRING_TAG);
((BerString*)hrdevdesc)->copy(tekbuf, 256);
char *begin=strstr(tekbuf,"Inc., ");
if (begin) {
char buf2[50];
begin+=6;
int len=strchr(begin,',')-begin;
strncpy(buf2,begin,len);
buf2[len]=0;
snprintf(buf,MAXSTR,"model=\"%s\";",buf2);
session.printstr(argflags,NEEDNL_ENTRY,buf);
} else {
fprintf(stderr,
"%s: Can't find \"Inc., \" in \"%s\"\n",
session.Hostname(),tekbuf);
}
delete modelresp;
}
} else if(!strncmp(gpi.sysDesc,XEROXSTR,5)){
if(CK_VENDOR_FLAG)
session.printstr(argflags,NEEDNL_ENTRY,"vendor=\"Xerox\";");
if(strstr(gpi.sysDesc,"???")){
if(CK_MODEL_FLAG)
not_sup("model",session.Hostname());
operflags|=XER_VENDOR;
} else {
if(CK_MODEL_FLAG){
char *model=strchr(gpi.sysDesc,' ')+1;
snprintf(buf,MAXSTR,"model=\"%s\";",model);
session.printstr(argflags,NEEDNL_ENTRY,buf);
}
operflags|=HAS_HOSTMIB_FLAG|HAS_PRINTMIB_FLAG|XER_VENDOR;
}
} else if(!strncmp(gpi.sysDesc,XEROXDC230STR,14) ||
!strncmp(gpi.sysDesc,XEROXDC230STR2,10)){
operflags|=HAS_HOSTMIB_FLAG|HAS_PRINTMIB_FLAG|XER_VENDOR;
if(CK_VENDOR_FLAG)
session.printstr(argflags,NEEDNL_ENTRY,"vendor=\"Xerox\";");
if(CK_MODEL_FLAG)
session.printstr(argflags,NEEDNL_ENTRY,
"model=\"Document Centre 230ST\";");
} else if(!strncmp(gpi.sysDesc,XEROXDC265STR,9)){
operflags|=HAS_HOSTMIB_FLAG|HAS_PRINTMIB_FLAG|XER_VENDOR;
if(CK_VENDOR_FLAG)
session.printstr(argflags,NEEDNL_ENTRY,"vendor=\"Xerox\";");
if(CK_MODEL_FLAG)
session.printstr(argflags,NEEDNL_ENTRY,
"model=\"Document Centre 265\";");
} else if(!strncmp(gpi.sysDesc,QMSSTR,3)){
operflags|=QMS_VENDOR;
if(CK_VENDOR_FLAG)
session.printstr(argflags,NEEDNL_ENTRY,"vendor=\"QMS\";");
if(CK_MODEL_FLAG){
strtok(gpi.sysDesc,";");
snprintf(buf,MAXSTR,"model=\"%s\";",gpi.sysDesc+4);
session.printstr(argflags,NEEDNL_ENTRY,buf);
}
} else if(!strncmp(gpi.sysDesc,IBMSTR,3)){
operflags|=IBM_VENDOR;
if(CK_VENDOR_FLAG)
session.printstr(argflags,NEEDNL_ENTRY,"vendor=\"IBM\";");
if(CK_MODEL_FLAG){
strtok(gpi.sysDesc+4," ");
snprintf(buf,MAXSTR,"model=\"%s\";",gpi.sysDesc+4);
session.printstr(argflags,NEEDNL_ENTRY,buf);
}
} else if(!strncmp(gpi.sysDesc,EFISTR,strlen(EFISTR)) ||
!strncmp(gpi.sysDesc,EFISTR2,strlen(EFISTR))){
operflags|=HAS_HOSTMIB_FLAG|EFI_VENDOR;
if(CK_VENDOR_FLAG)
session.printstr(argflags,NEEDNL_ENTRY,"vendor=\"EFI\";");
if(CK_MODEL_FLAG)
not_sup("model",session.Hostname());
} else if(!strncmp(gpi.sysDesc,FUJISTR,strlen(FUJISTR))){
/* I think that this was a mistake and so I commented this
out. However, there might be a fuji printer out there
somewhere which does support the host mib and the print
mib. If there is then we will have to make a much more
exacting test. */
// operflags|=HAS_HOSTMIB_FLAG|FUJI_VENDOR;
if(CK_VENDOR_FLAG)
session.printstr(argflags,NEEDNL_ENTRY,"vendor=\"Fuji\";");
if(CK_MODEL_FLAG)
session.printstr(argflags,NEEDNL_ENTRY,"model=\"Able PRII\";");
/* Hopefully none of these give false positives. This sort of filter's
out some of the more obvious non-printer snmp services */
} else if(!strstr(gpi.sysDesc,"HP-UX") || !strstr(gpi.sysDesc,"HPUX") ||
!strstr(gpi.sysDesc,"Windows NT") ||
!strstr(gpi.sysDesc,"Sun SNMP Agent") ||
!strstr(gpi.sysDesc,"SunOS") ||
!strstr(gpi.sysDesc,"Macintosh") ||
!strstr(gpi.sysDesc,"UNIX")){
fprintf(stderr,
"Warning: %s does not appear to be a printer. Skipping.\n",
session.Hostname());
int *i=new int;
assert(i);
*i=ERR_NOT_PRINTER;
pthread_exit(i);
} else {
char *connhost=session.ConnHost();
fprintf(stderr,"Warning: %s: unknown printer vendor. Describes itself "
"as \"%s\"\n",session.Hostname(),gpi.sysDesc);
int *i=new int;
assert(i);
*i=ERR_UNKNOWN_DEVICE;
pthread_exit(i);
}
}
/* ------- print out the contact information --------------------------- */
if(CK_CONTACT_FLAG){
snprintf(buf,MAXSTR,"contact=\"%s\";location=\"%s\";",
gpi.sysContact?gpi.sysContact:"",
gpi.sysLocation?gpi.sysLocation:"");
session.printstr(argflags,NEEDNL_ENTRY,buf);
}
if(CK_HOSTMIB_FLAG){
snprintf(buf,MAXSTR,"hostmib=\"%c\";",operflags&HAS_HOSTMIB_FLAG?'Y':'N');
session.printstr(argflags,NEEDNL_ENTRY,buf);
}
if(CK_PRINTMIB_FLAG){
snprintf(buf,MAXSTR,"printmib=\"%c\";",
operflags&HAS_PRINTMIB_FLAG?'Y':'N');
session.printstr(argflags,NEEDNL_ENTRY,buf);
}
}
void do_connections(unsigned long *argflags,SNMP_session &session,
ConnectionInfoRequest *cir){
ConnectionInfoRequest *cur=cir;
while(cur){
SNMP_table conntabreq(session, sizeof(ConnectionInfo));
assert(cur->statebuf=new char[1024]);
int len=strlen(TCPCONNSTATE_BASE);
/* we can assume that this worked otherwise the session would
have failed above and we can also assume that printers
only have one ip address right? */
strcpy(cur->statebuf,TCPCONNSTATE_BASE);
// append the ipaddress and the port to the base oid
len+=sprintf(cur->statebuf+strlen(cur->statebuf),".%u.%u.%u.%u.%u",
((unsigned)session.ConnHost()[0] & 0xff),
((unsigned)session.ConnHost()[1] & 0xff),
((unsigned)session.ConnHost()[2] & 0xff),
((unsigned)session.ConnHost()[3] & 0xff),
((unsigned)cur->port & 0xffff))+1;
cur->statebuf=(char*)realloc(cur->statebuf,len+1);
conntabreq.append(cur->statebuf,INT_TAG,
((char*)&(DUMMY_CONNINFO.connState))-
(char*)&DUMMY_CONNINFO);
cur->remaddrbuf=new char[1024];
len=strlen(TCPCONNREMADDRESS_BASE);
char *p=session.ConnHost();
strcpy(cur->remaddrbuf,TCPCONNREMADDRESS_BASE);
// append the ipaddress and the port to the base oid
len+=sprintf(cur->remaddrbuf+strlen(cur->remaddrbuf),".%u.%u.%u.%u.%u",
((unsigned)p[0] & 0xff),((unsigned)p[1] & 0xff),
((unsigned)p[2] & 0xff),((unsigned)p[3] & 0xff),
((unsigned)cur->port & 0xffff))+1;
cur->remaddrbuf=(char*)realloc(cur->remaddrbuf,len+1);
conntabreq.append(cur->remaddrbuf,IPADDR_TAG,
((char*)&(DUMMY_CONNINFO.remhost))-
(char*)&DUMMY_CONNINFO);
unsigned int numrecords;
try{
cur->conninfo=(ConnectionInfo*)conntabreq.get(numrecords);
} catch (SNMP_error_unrecoverable &error){
handle_unrecoverable(progname, session.Hostname(),error);
}
cur=cur->next;
}
// print out connection info
for(cur=cir;cur!=NULL;cur=cur->next){
char buf[MAXSTR];
assert(cur->conninfo->connState>0 && cur->conninfo->connState<=11);
snprintf(buf,MAXSTR,
"port=\"%u\";state=\"%s\";remotehost=\"%u.%u.%u.%u\"\n",
cur->port,TCPSTATES[cur->conninfo->connState],
((unsigned)cur->conninfo->remhost[0] & 0xff),
((unsigned)cur->conninfo->remhost[1] & 0xff),
((unsigned)cur->conninfo->remhost[2] & 0xff),
((unsigned)cur->conninfo->remhost[3] & 0xff));
session.printstr(argflags,NEEDNL_LINE,buf);
}
}
void do_hostmib_get(SNMP_session &session, unsigned long *argflags,
unsigned long &operflags){
if(CK_MEMORY_FLAG || CK_STATUS_FLAG){
HostPrinterInfo hprinfo;
char buf[MAXSTR];
SNMP_structFiller getreq(session);
if(CK_MEMORY_FLAG)
getreq.append(HRMEMORYSIZE,INT_TAG,
(char*)&(hprinfo.memsize)-(char*)&hprinfo);
if(CK_STATUS_FLAG)
getreq.append(HRPRINTERSTATUS,INT_TAG,
(char*)&(hprinfo.prstatus)-(char*)&hprinfo);
char retry=0;
do{
try{
getreq.get(&hprinfo);
retry=0;
} catch(SNMP_error_unrecoverable &error){
handle_unrecoverable(progname, session.Hostname(),error);
} catch(SNMP_error_oid *error){
assert(retry<=2); //something is bad the request is looping
if(*error==HRMEMORYSIZE){
/* this is a hack that takes care of a xerox printer that
stores it in .1 rather than .0 */
getreq.remove(HRMEMORYSIZE);
getreq.append(HRMEMORYSIZE1,INT_TAG,
(char*)&(hprinfo.memsize)-(char*)&hprinfo);
retry++;
} else if(*error==HRPRINTERSTATUS && operflags&HP_VENDOR){
getreq.remove(HRPRINTERSTATUS);
fprintf(stderr,
"Warning: %s has an old firmware. Please upgrade it!\n",
session.Hostname());
do_hppriv_get(session,argflags,operflags);
if(CK_MEMORY_FLAG) // only retry if there is another oid
retry++;
} else {
assert(0); //tell me about this something went really wrong
}
}
}while(retry);
if(CK_MEMORY_FLAG){
snprintf(buf,MAXSTR,"memsize=\"%u\";",hprinfo.memsize);
session.printstr(argflags,NEEDNL_ENTRY,buf);
}
if(CK_STATUS_FLAG){
assert(hprinfo.prstatus>=0 && hprinfo.prstatus<=5 &&
HRSTATUSSTATES[hprinfo.prstatus]!=NULL);
snprintf(buf,MAXSTR,"status=\"%s\";",HRSTATUSSTATES[hprinfo.prstatus]);
session.printstr(argflags,NEEDNL_ENTRY,buf);
}
}
if(CK_STORAGE_FLAG){
HrStorageTable *storage;
unsigned int len;
SNMP_table stortabreq(session,sizeof(HrStorageTable));
stortabreq.append(HRSSTORAGEDESCR_BASE,STRING_TAG,
(char*)&BHSID.desc-(char*)&BHSID);
stortabreq.append(HRSTORAGEALLOCATIONUNITS_BASE,INT_TAG,
(char*)&BHSID.allocunits-(char*)&BHSID);
stortabreq.append(HRSTORAGESIZE_BASE,INT_TAG,
(char*)&BHSID.size-(char*)&BHSID);
stortabreq.append(HRSTORAGEUSED_BASE,INT_TAG,
(char*)&BHSID.used-(char*)&BHSID);
stortabreq.append(HRSTORAGEALLOCATIONFAILURES_BASE,COUNTER_TAG,
(char*)&BHSID.failures-(char*)&BHSID);
try{
assert(storage=(HrStorageTable*)stortabreq.get(len));
} catch (SNMP_error_unrecoverable &error){
handle_unrecoverable(progname, session.Hostname(),error);
}
while(len){
len--;
char buf[MAXSTR];
snprintf(buf,MAXSTR,"desc=\"%s\";allocunits=\"%u\";size=\"%u\";"
"used=\"%u\";allocfail=\"%u\";\n",storage[len].desc,
storage[len].allocunits,storage[len].size,storage[len].used,
storage[len].failures);
session.printstr(argflags,NEEDNL_ENTRY,buf);
}
delete storage;
}
}
void hpcfgsrc(SNMP_session &session,unsigned long *argflags,
BerBase *cfgsrcdat){
assert(cfgsrcdat->type()==INT_TAG);
unsigned long cfgtype=((BerInt*)cfgsrcdat)->value();
assert(cfgtype<=5 && HPCFGSOURCESTATES[cfgtype]!=NULL);
char buf[MAXSTR];
snprintf(buf,MAXSTR,"cfgsrc=\"%s\";",HPCFGSOURCESTATES[cfgtype]);
session.printstr(argflags,NEEDNL_ENTRY,buf);
}
syntax highlighted by Code2HTML, v. 0.9.1