blob: 05739b5c617b764ccb163103a85095a0826a72aa [file] [log] [blame]
/*
* snmpd.c - rrespond to SNMP queries from management stations
*
*/
/***********************************************************
Copyright 1988, 1989 by Carnegie Mellon University
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of CMU not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/
#include <config.h>
#include <sys/types.h>
#if HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#include <stdio.h>
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#include <sys/socket.h>
#include <errno.h>
#include <net/if.h>
#if HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#include "snmp.h"
#include "asn1.h"
#include "snmp_impl.h"
#include "system.h"
#include "snmp_api.h"
#include "m2m.h"
#include "party.h"
#include "alarm.h"
#include "view.h"
#include "context.h"
#include "acl.h"
extern int errno;
int snmp_dump_packet = 0;
int log_addresses = 0;
struct addrCache {
u_long addr;
int status;
#define UNUSED 0
#define USED 1
#define OLD 2
};
static struct addrCache addrCache[10];
static int lastAddrAge = 0;
#ifndef FD_SET
#include <sys/param.h>
typedef long fd_mask;
#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */
#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
#endif
/*
* In: My ip address, View subtree
* Initializes a noAuth/noPriv party pair, a context, 2 acl entries, and
* a view subtree. (Are two acl entries really needed?)
* The view subtree is included by default and has no Mask.
* Out: returns 0 if OK, 1 if conflict with a pre-installed
* party/context/acl/view, -1 if an error occurred.
*/
agent_party_init(myaddr, view)
u_long myaddr;
char *view;
{
u_long addr;
u_short port;
oid partyid1[64];
int partyidlen1;
oid partyid2[64];
int partyidlen2;
oid contextid[64];
int contextidlen;
struct partyEntry *pp1, *pp2, *rp;
struct contextEntry *cxp, *rxp;
int viewIndex;
oid viewSubtree[64];
int viewSubtreeLen;
struct viewEntry *vwp;
struct aclEntry *ap;
int oneIndex, twoIndex, cxindex;
/*
* Check for existence of the party, context, acl, and view and
* exit if any of them exist. We must create the parties to get the
* partyIndexes for acl creation, so we delete these parties if we
* fail anywhere else.
*/
/* This would be better written as follows:
We currently check for the existence of each of the
src/dst/context/acl/view entries before creating anything.
The problem is that in order to check for the existence of the
acl entry, we need to create the src/dst/context to get their
indexes. So we create them with the proviso that we delete them
if checks for other src/dst/context/view/acl fail. [BUG: we don't
delete context and view if acl fails or context if view fails].
Observation: Because each index for the acl table is taken from
a newly-created and therefore unique src/dst/context index, there
is no reason to check for the existence of such an acl entry.
Therefore, there is no reason to create the party entries until
*after* we have checked everything. This greatly simplifies this code.
In addition, nobody cares what the view index is, so there is no need
to check for the view's existence (just choose something that isn't
in use.
Suggestion:
check src
check dst
check context
if any used, fail 1
create src, dst, context
create acl(src.index, dst.index, context.index) and its brother
find an unused view index (preferably one)
create viewEntry(viewIndex, viewSubtree)
context.viewIndex = viewIndex
*/
partyidlen1 = 64;
if (!read_objid(".1.3.6.1.6.3.3.1.3.128.2.35.55.1",
partyid1, &partyidlen1)){
fprintf(stderr, "Bad object identifier: %s\n",
".1.3.6.1.6.3.3.1.3.128.2.35.55.1");
return -1;
}
partyid1[9] = (myaddr & 0xFF000000) >> 24;
partyid1[10] = (myaddr & 0x00FF0000) >> 16;
partyid1[11] = (myaddr & 0x0000FF00) >> 8;
partyid1[12] = (myaddr & 0x000000FF);
partyid1[13] = 1;
pp1 = party_getEntry(partyid1, partyidlen1);
if (pp1){
return 1;
}
pp1 = party_createEntry(partyid1, partyidlen1);
oneIndex = pp1->partyIndex;
partyidlen2 = 64;
if (!read_objid(".1.3.6.1.6.3.3.1.3.128.2.35.55.1",
partyid2, &partyidlen2)){
fprintf(stderr, "Bad object identifier: %s\n",
".1.3.6.1.6.3.3.1.3.128.2.35.55.1");
party_destroyEntry(partyid1, partyidlen1);
return -1;
}
partyid2[9] = (myaddr & 0xFF000000) >> 24;
partyid2[10] = (myaddr & 0x00FF0000) >> 16;
partyid2[11] = (myaddr & 0x0000FF00) >> 8;
partyid2[12] = (myaddr & 0x000000FF);
partyid2[13] = 2;
pp2 = party_getEntry(partyid2, partyidlen2);
if (pp2){
party_destroyEntry(partyid1, partyidlen1);
return 1;
}
pp2 = party_createEntry(partyid2, partyidlen2);
twoIndex = pp2->partyIndex;
contextidlen = 64;
if (!read_objid(".1.3.6.1.6.3.3.1.4.128.2.35.55.1",
contextid, &contextidlen)){
fprintf(stderr, "Bad object identifier: %s\n",
".1.3.6.1.6.3.3.1.4.128.2.35.55.1");
party_destroyEntry(partyid1, partyidlen1);
party_destroyEntry(partyid2, partyidlen2);
return -1;
}
contextid[9] = (myaddr & 0xFF000000) >> 24;
contextid[10] = (myaddr & 0x00FF0000) >> 16;
contextid[11] = (myaddr & 0x0000FF00) >> 8;
contextid[12] = (myaddr & 0x000000FF);
contextid[13] = 1;
cxp = context_getEntry(contextid, contextidlen);
if (cxp){
party_destroyEntry(partyid1, partyidlen1);
party_destroyEntry(partyid2, partyidlen2);
return 1;
}
viewIndex = 1;
viewSubtreeLen = 64;
if (!read_objid(view, viewSubtree, &viewSubtreeLen)){
fprintf(stderr, "Bad object identifier: %s\n", view);
party_destroyEntry(partyid1, partyidlen1);
party_destroyEntry(partyid2, partyidlen2);
return -1;
}
vwp = view_getEntry(viewIndex, viewSubtree, viewSubtreeLen);
if (vwp){
party_destroyEntry(partyid1, partyidlen1);
party_destroyEntry(partyid2, partyidlen2);
return 1;
}
ap = acl_getEntry(oneIndex, twoIndex, 1);
if (ap){
party_destroyEntry(partyid1, partyidlen1);
party_destroyEntry(partyid2, partyidlen2);
return 1;
}
ap = acl_getEntry(twoIndex, oneIndex, 1);
if (ap){
party_destroyEntry(partyid1, partyidlen1);
party_destroyEntry(partyid2, partyidlen2);
return 1;
}
rp = pp1->reserved;
strcpy(pp1->partyName, "noAuthAgent");
pp1->partyTDomain = rp->partyTDomain = DOMAINSNMPUDP;
addr = htonl(myaddr);
port = htons(161);
bcopy((char *)&addr, pp1->partyTAddress, sizeof(addr));
bcopy((char *)&port, pp1->partyTAddress + 4, sizeof(port));
bcopy(pp1->partyTAddress, rp->partyTAddress, 6);
pp1->partyTAddressLen = rp->partyTAddressLen = 6;
pp1->partyAuthProtocol = rp->partyAuthProtocol = NOAUTH;
pp1->partyAuthClock = rp->partyAuthClock = 0;
pp1->tv.tv_sec = pp1->partyAuthClock;
pp1->partyAuthPublicLen = 0;
pp1->partyAuthLifetime = rp->partyAuthLifetime = 0;
pp1->partyPrivProtocol = rp->partyPrivProtocol = NOPRIV;
pp1->partyPrivPublicLen = 0;
pp1->partyMaxMessageSize = rp->partyMaxMessageSize = 1500;
pp1->partyLocal = 1; /* TRUE */
pp1->partyAuthPrivateLen = rp->partyAuthPrivateLen = 0;
pp1->partyPrivPrivateLen = rp->partyPrivPrivateLen = 0;
pp1->partyStorageType = 2; /* volatile */
pp1->partyStatus = rp->partyStatus = PARTYACTIVE;
#define PARTYCOMPLETE_MASK 65535
/* all collumns - from party_vars.c XXX */
pp1->partyBitMask = rp->partyBitMask = PARTYCOMPLETE_MASK;
rp = pp2->reserved;
strcpy(pp2->partyName, "noAuthMS");
pp2->partyTDomain = rp->partyTDomain = DOMAINSNMPUDP;
bzero(pp2->partyTAddress, 6);
bcopy(pp2->partyTAddress, rp->partyTAddress, 6);
pp2->partyTAddressLen = rp->partyTAddressLen = 6;
pp2->partyAuthProtocol = rp->partyAuthProtocol = NOAUTH;
pp2->partyAuthClock = rp->partyAuthClock = 0;
pp2->tv.tv_sec = pp2->partyAuthClock;
pp2->partyAuthPublicLen = 0;
pp2->partyAuthLifetime = rp->partyAuthLifetime = 0;
pp2->partyPrivProtocol = rp->partyPrivProtocol = NOPRIV;
pp2->partyPrivPublicLen = 0;
pp2->partyMaxMessageSize = rp->partyMaxMessageSize = 484; /* ??? */
pp2->partyLocal = 2; /* FALSE */
pp2->partyAuthPrivateLen = rp->partyAuthPrivateLen = 0;
pp2->partyPrivPrivateLen = rp->partyPrivPrivateLen = 0;
pp2->partyStorageType = 2; /* volatile */
pp2->partyStatus = rp->partyStatus = PARTYACTIVE;
pp2->partyBitMask = rp->partyBitMask = PARTYCOMPLETE_MASK;
cxp = context_createEntry(contextid, contextidlen);
rxp = cxp->reserved;
strcpy(cxp->contextName, "noAuthContext");
cxp->contextLocal = 1; /* TRUE */
cxp->contextViewIndex = 1;
cxp->contextLocalEntityLen = 0;
cxp->contextLocalTime = CURRENTTIME;
cxp->contextProxyContextLen = 0;
cxp->contextStorageType = 2;
cxp->contextStatus = rxp->contextStatus = CONTEXTACTIVE;
#define CONTEXTCOMPLETE_MASK 0x03FF
/* all collumns - from context_vars.c XXX */
cxp->contextBitMask = rxp->contextBitMask = CONTEXTCOMPLETE_MASK;
cxindex = cxp->contextIndex;
vwp = view_createEntry(viewIndex, viewSubtree, viewSubtreeLen);
vwp->viewType = VIEWINCLUDED;
vwp->viewMaskLen = 0;
vwp->viewStorageType = 2; /* volatile */
vwp->viewStatus = VIEWACTIVE;
#define VIEWCOMPLETE_MASK 0x3F
/* all collumns - from view_vars.c XXX */
vwp->viewBitMask = VIEWCOMPLETE_MASK;
vwp->reserved->viewBitMask = vwp->viewBitMask;
viewSubtreeLen = 64;
if (!read_objid(".2.6.6", viewSubtree, &viewSubtreeLen)){
fprintf(stderr, "Bad object identifier: .2.6.6\n");
return -1;
}
vwp = view_createEntry(viewIndex, viewSubtree, viewSubtreeLen);
vwp->viewType = VIEWINCLUDED;
vwp->viewMaskLen = 0;
vwp->viewStorageType = 2; /* volatile */
vwp->viewStatus = VIEWACTIVE;
vwp->viewBitMask = VIEWCOMPLETE_MASK;
vwp->reserved->viewBitMask = vwp->viewBitMask;
ap = acl_createEntry(oneIndex, twoIndex, cxindex);
ap->aclPriveleges = 132;
ap->aclStorageType = 2; /* volatile */
ap->aclStatus = ACLACTIVE;
#define ACLCOMPLETE_MASK 0x3F
/* all collumns - from acl_vars.c XXX */
ap->aclBitMask = ACLCOMPLETE_MASK;
ap->reserved->aclBitMask = ap->aclBitMask;
ap = acl_createEntry(twoIndex, oneIndex, cxindex);
/* To play around with SETs with a minimum of hassle, set this to 43
and noAuth/noPriv parties will be able to set in this default view.
Remember to turn it back off when you're done! */
ap->aclPriveleges = 35;
ap->aclStorageType = 2; /* volatile */
ap->aclStatus = ACLACTIVE;
ap->aclBitMask = ACLCOMPLETE_MASK;
ap->reserved->aclBitMask = ap->aclBitMask;
return 0; /* SUCCESS */
}
char *reverse_bytes(buf,num)
char *buf;
int num;
{
static char outbuf[100];
int i;
for(i=num-1;i>=0;i--)
outbuf[i] = *buf++;
return(outbuf);
}
char **argvrestartp;
char *argvrestart;
char *argvrestartname;
extern char *VersionInfo;
void usage(prog)
char *prog;
{
printf("\nUsage: %s [-h] [-v] [-f] [-a] [-d] [-q] [-L] [-l LOGFILE]\n",prog);
printf("\n\tVersion: %s\n",VersionInfo);
printf("\tAuthor: hardaker@ece.ucdavis.edu\n");
printf("\n-h\t\tThis usage message.\n");
printf("-v\t\tVersion information.\n");
printf("-f\t\tDon't fork from the shell.\n");
printf("-a\t\tLog addresses.\n");
printf("-d\t\tDump sent and received UDP SNMP packets\n");
printf("-q\t\tPrint information in a more parsable format (quick-print)\n");
printf("-L\t\tPrint warnings/messages to stdout/err rather than a logfile\n");
printf("-l LOGFILE\tPrint warnings/messages to LOGFILE\n");
printf("\t\t(By default LOGFILE=%s)\n",
#ifdef LOGFILE
LOGFILE
#else
"stdout/err"
#endif
);
printf("\n");
exit(1);
}
main(argc, argv)
int argc;
char *argv[];
{
int arg,i;
int sd, sdlist[32], portlist[32], sdlen = 0, index;
struct sockaddr_in me;
int port_flag = 0, ret;
u_short dest_port = 0;
struct partyEntry *pp;
u_long myaddr;
int on=1;
int dont_fork=0;
char logfile[300];
char *cptr, **argvptr;
logfile[0] = NULL;
#ifdef LOGFILE
strcpy(logfile,LOGFILE);
#endif
/*
* usage: snmpd
*/
for(arg = 1; arg < argc; arg++){
if (argv[arg][0] == '-'){
switch(argv[arg][1]){
case 'd':
snmp_dump_packet++;
break;
case 'q':
quick_print++;
break;
case 'p':
port_flag++;
dest_port = atoi(argv[++arg]);
break;
case 'a':
log_addresses++;
break;
case 'f':
dont_fork=1;
break;
case 'l':
strcpy(logfile,argv[++arg]);
break;
case 'L':
logfile[0] = NULL;
break;
case 'h':
usage(argv[0]);
break;
case 'v':
printf("\nUcd-snmp version: %s\n",VersionInfo);
printf("Author: hardaker@ece.ucdavis.edu\n\n");
exit (0);
default:
printf("invalid option: -%c\n", argv[arg][1]);
usage(argv[0]);
break;
}
continue;
}
}
/* initialize a argv set to the current for restarting the agent */
argvrestartp = (char **) malloc((argc+2) * sizeof (char *));
argvptr = argvrestartp;
for(i=0, ret = 1; i < argc; i++) {
ret += strlen(argv[i])+1;
}
argvrestart = (char *) malloc((ret));
argvrestartname = (char *) malloc(strlen(argv[0]));
strcpy(argvrestartname,argv[0]);
for(cptr = argvrestart,i = 0; i < argc; i++) {
strcpy(cptr,argv[i]);
*(argvptr++) = cptr;
cptr += strlen(argv[i]) + 1;
}
*cptr = NULL;
*argvptr = NULL;
/* open the logfile if necessary */
if (logfile[0]) {
close(1);
open(LOGFILE,O_WRONLY|O_TRUNC|O_CREAT,0644);
close(2);
dup(1);
close(0);
}
if (!dont_fork && fork() != 0) /* detach from shell */
exit(0);
init_snmp();
init_mib();
if (read_party_database("/etc/party.conf") > 0){
fprintf(stderr, "Couldn't read party database from /etc/party.conf\n");
exit(0);
}
if (read_context_database("/etc/context.conf") > 0){
fprintf(stderr, "Couldn't read context database from /etc/context.conf\n");
exit(0);
}
if (read_acl_database("/etc/acl.conf") > 0){
fprintf(stderr, "Couldn't read acl database from /etc/acl.conf\n");
exit(0);
}
if (read_view_database("/etc/view.conf") > 0){
fprintf(stderr, "Couldn't read view database from /etc/view.conf\n");
exit(0);
}
myaddr = get_myaddr();
/* XXX mib-2 subtree only??? */
if (ret = agent_party_init(myaddr, ".iso.org.dod.internet")){
if (ret == 1){
fprintf(stderr, "Conflict found with initial noAuth/noPriv parties... continuing\n");
} else if (ret == -1){
fprintf(stderr, "Error installing initial noAuth/noPriv parties, exiting\n");
exit(1);
} else {
fprintf(stderr, "Unknown error, exiting\n");
exit(2);
}
}
printf("Opening port(s): ");
fflush(stdout);
party_scanInit();
for(pp = party_scanNext(); pp; pp = party_scanNext()){
#if WORDS_BIGENDIAN
if ((pp->partyTDomain != DOMAINSNMPUDP)
|| bcmp((char *)&myaddr, pp->partyTAddress, 4))
continue; /* don't listen for non-local parties */
#else
if ((pp->partyTDomain != DOMAINSNMPUDP)
|| bcmp(reverse_bytes((char *)&myaddr,sizeof(long)),
pp->partyTAddress, 4))
continue; /* don't listen for non-local parties */
#endif
dest_port = 0;
#if WORDS_BIGENDIAN
bcopy(pp->partyTAddress + 4, &dest_port, 2);
#else
bcopy(reverse_bytes(pp->partyTAddress + 4,2), &dest_port, 2);
#endif
for(index = 0; index < sdlen; index++)
if (dest_port == portlist[index])
break;
if (index < sdlen) /* found a hit before the end of the list */
continue;
printf("%u ", dest_port);
fflush(stdout);
/* Set up connections */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0){
perror("socket");
return 1;
}
me.sin_family = AF_INET;
me.sin_addr.s_addr = INADDR_ANY;
/* already in network byte order (I think) */
me.sin_port = htons(dest_port);
if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){
fprintf(stderr,"bind/%d",me.sin_port);
perror("bind");
return 2;
}
sdlist[sdlen] = sd;
portlist[sdlen] = dest_port;
fcntl(sd,F_SETFD,1); /* close on exec */
if (++sdlen == 32){
printf("No more sockets... ignoring rest of file\n");
break;
}
}
printf("\n");
fflush(stdout);
bzero((char *)addrCache, sizeof(addrCache));
receive(sdlist, sdlen);
return 0;
}
receive(sdlist, sdlen)
int sdlist[];
int sdlen;
{
int numfds, index;
fd_set fdset;
struct timeval timeout, *tvp = &timeout;
struct timeval sched, *svp = &sched, now, *nvp = &now;
int count, block;
int counter = 0;
#ifdef hpux
gettimeofday(nvp, (struct timezone *) NULL);
#else
gettimeofday(nvp);
#endif
if (nvp->tv_usec < 500000L){
svp->tv_usec = nvp->tv_usec + 500000L;
svp->tv_sec = nvp->tv_sec;
} else {
svp->tv_usec = nvp->tv_usec - 500000L;
svp->tv_sec = nvp->tv_sec + 1;
}
while(1){
#if 0
if (counter++ == 8000)
exit(0);
#endif
tvp = &timeout;
tvp->tv_sec = 0;
tvp->tv_usec = 500000L;
numfds = 0;
FD_ZERO(&fdset);
for(index = 0; index < sdlen; index++){
if (sdlist[index] + 1 > numfds)
numfds = sdlist[index] + 1;
FD_SET(sdlist[index], &fdset);
}
block = 0;
snmp_select_info(&numfds, &fdset, tvp, &block);
if (block == 1)
tvp = NULL; /* block without timeout */
count = select(numfds, (int *) &fdset, 0, 0, tvp);
if (count > 0){
for(index = 0; index < sdlen; index++){
if(FD_ISSET(sdlist[index], &fdset)){
snmp_read_packet(sdlist[index]);
FD_CLR(sdlist[index], &fdset);
}
}
snmp_read(&fdset);
} else switch(count){
case 0:
snmp_timeout();
break;
case -1:
if (errno == EINTR){
continue;
} else {
perror("select");
}
return -1;
default:
printf("select returned %d\n", count);
return -1;
}
#ifdef hpux
gettimeofday(nvp, (struct timezone *) NULL);
#else
gettimeofday(nvp);
#endif
if (nvp->tv_sec > svp->tv_sec
|| (nvp->tv_sec == svp->tv_sec && nvp->tv_usec > svp->tv_usec)){
alarmTimer(nvp);
eventTimer(nvp);
if (nvp->tv_usec < 500000L){
svp->tv_usec = nvp->tv_usec + 500000L;
svp->tv_sec = nvp->tv_sec;
} else {
svp->tv_usec = nvp->tv_usec - 500000L;
svp->tv_sec = nvp->tv_sec + 1;
}
if (log_addresses && lastAddrAge++ > 600){
int count;
lastAddrAge = 0;
for(count = 0; count < 10; count++){
if (addrCache[count].status == OLD)
addrCache[count].status = UNUSED;
if (addrCache[count].status == USED)
addrCache[count].status = OLD;
}
}
}
}
}
snmp_read_packet(sd)
int sd;
{
struct sockaddr_in from;
int length, out_length, fromlength;
u_char packet[1500], outpacket[1500];
fromlength = sizeof from;
length = recvfrom(sd, packet, 1500, 0, (struct sockaddr *)&from,
&fromlength);
if (length == -1)
perror("recvfrom");
if (snmp_dump_packet){
printf("recieved %d bytes from %s:\n", length,
inet_ntoa(from.sin_addr));
xdump(packet, length, "");
printf("\n\n");
} else if (log_addresses){
int count;
for(count = 0; count < 10; count++){
if (addrCache[count].status > 0 /* used or old */
&& from.sin_addr.s_addr == addrCache[count].addr)
break;
}
if (count >= 10){
printf("Recieved SNMP packet(s) from %s\n",
inet_ntoa(from.sin_addr));
for(count = 0; count < 10; count++){
if (addrCache[count].status == UNUSED){
addrCache[count].addr = from.sin_addr.s_addr;
addrCache[count].status = USED;
break;
}
}
} else {
addrCache[count].status = USED;
}
}
out_length = 1500;
if (snmp_agent_parse(packet, length, outpacket, &out_length,
from.sin_addr.s_addr)){
if (snmp_dump_packet){
printf("sent %d bytes to %s:\n", out_length,
inet_ntoa(from.sin_addr));
xdump(outpacket, out_length, "");
printf("\n\n");
}
if (sendto(sd, (char *)outpacket, out_length, 0,
(struct sockaddr *)&from,
sizeof(from)) < 0){
perror("sendto");
return 0;
}
}
return 1;
}
/* deals with replies from remote alarm variables, and from inform pdus */
int
snmp_input(op, session, reqid, pdu, magic)
int op;
struct snmp_session *session;
int reqid;
struct snmp_pdu *pdu;
void *magic;
{
struct get_req_state *state = (struct get_req_state *)magic;
if (op == RECEIVED_MESSAGE) {
if (pdu->command == GET_RSP_MSG) {
if (state->type == EVENT_GET_REQ) {
/* this is just the ack to our inform pdu */
return 1;
}
return alarmGetResponse(pdu, state, op, session);
}
}
else if (op == TIMED_OUT) {
if (state->type == ALARM_GET_REQ) {
return alarmGetResponse(pdu, state, op, session);
}
}
return 1;
}