/******************************************************************************
**
**                      query.c
**
** Top level function to perform querying of an agent.
**
**
******************************************************************************/
#ifdef BSD
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/time.h>
#endif /* BSD */
#include "include.h"
#include "conf.h"
#include "snmp_hs.h"
#include "cmon.h"


static jmp_buf env;
short retries;				/* number of retries */


int
query(a)
     AGENT *a;
{
  struct itimerval interval,disable;    /* for timeouts and retries */
  getreq req;                           /* the request message */
  getrsp rsp;                           /* buffer for reply */
  struct in_addr from;                  /* source of message received */
  long rreq_id;                         /* req id of message received */
  short type;                           /* type of message received */
  char r_sid[SNMPMXSID];                /* community id of message received */
  short sidlen;                         /* length of community id */
  short rc;                             /* return code */
  int sonintr();                        /* timeout interrupt handler */

/* initializations */
/* timing structures */
  interval.it_interval.tv_sec = 0;    /* don't want to reload timer */
  interval.it_interval.tv_usec = 0;
  interval.it_value.tv_usec = 0;
  disable.it_interval.tv_sec = 0;     /* to disable timer */
  disable.it_interval.tv_usec = 0;
  disable.it_value.tv_sec = 0;
  disable.it_value.tv_usec = 0;

/* request message */
  req.errstat = req.errindex = 0;
  req.varlist.len = 1;                  /* one variable */
  req.varlist.elem[0].name.cmp[0] = 0x01; /* iso */
  req.varlist.elem[0].name.cmp[1] = 0x03; /* org */
  req.varlist.elem[0].name.cmp[2] = 0x06; /* dod */
  req.varlist.elem[0].name.cmp[3] = 0x01; /* internet */
  req.varlist.elem[0].name.cmp[4] = 0x04; /* enterprise */
  req.varlist.elem[0].name.cmp[5] = 0x01; /* mib */
  req.varlist.elem[0].name.cmp[6] = 0x14; /* MIT */
  req.varlist.elem[0].name.cmp[7] = 0x01; /* Athena */
  req.varlist.elem[0].name.cmp[8] = 0x03; /* status */
  req.varlist.elem[0].name.cmp[9] = 0x04; /* stLogin */
  req.varlist.elem[0].name.cmp[10]= 0x00; /* instance */
  req.varlist.elem[0].name.ncmp = 11;   /* number of components */
  req.varlist.elem[0].val.type = EMPTY; /* no values in request */


/* do agent specific (re)initializations */
     req.reqid = (long)time((long *)NULL) ^ getpid();
     interval.it_value.tv_sec = 1;        /* HARD CODE 1 sec interval */
     retries = 0;

/* fprintf(stderr,"Poll: addr = %s\n",a->nm); */

/* preserve environment etc. */
     if(setjmp(env))
      if(retries < RETRIES)
       retries++;
      else                              /* exceeded number of retries */
       { 
         return(-1);
       }

/* send off request */
  (void) signal(SIGALRM,SIG_IGN);
     if((rc = snmpsend(REQ,req.reqid,&a->agnt,"snmp",&req,
                       COMMUNITY,strlen(COMMUNITY),TIMEOUT)) < 0)
       { error(rc,stderr);
         return(-1);
       }

/* receive reply */
     rreq_id = req.reqid;               /* save request id */
  (void) signal(SIGALRM,sonintr);
     setitimer(ITIMER_REAL,&interval,(struct itimerval *)NULL);
     if((type = snmprecv(&from,(char *)NULL,&rreq_id,r_sid,&sidlen,
                          (char *)&rsp,sizeof(rsp))) < 0)
      { error(type,stderr);
        longjmp(env,1);
      }
     setitimer(ITIMER_REAL,&disable,(struct itimerval *)NULL);

/* check reply */
     if(type != RSP)                    /* not a response */
      { fprintf(stderr,"Poll: did not receive a response to poll\n");
        longjmp(env,1);
      }
     if(rsp.errstat != 0)               /* error in message */
      { /* fprintf(stderr,"Poll: error in reply errstat = %d errindex = %d\n",
                        rsp.errstat,rsp.errindex); */
        return(-1);
      }
     if(rreq_id != req.reqid)           /* wrong request id */
      { fprintf(stderr,"Poll: wrong message received\n");
        longjmp(env,1);
      }
     if(oidncmp(&(req.varlist.elem[0].name),&(rsp.varlist.elem[0].name),
                req.varlist.elem[0].name.ncmp) != 0)
      { fprintf(stderr,"Poll: unknown variable received\n");
        longjmp(env,1);
      }
     if(rsp.varlist.elem[0].val.type != INT)    /* check value type */
      { fprintf(stderr,"Poll: variable was of wrong type\n");
      }

/* variable was correct, copy in value */
     a->status = rsp.varlist.elem[0].val.value.intgr;
     if(a->status>1)a->status=1;		/* clamp it at 1 */
     fprintf(stderr,"poll: Agent %s reports %d\n",a->nm, a->status);
  return(0);
}

sonintr()
{
  longjmp(env,1);
}
