This is snmp.c in view mode; [Download] [Up]
/*
* $Header: /disk/d/src/devel/gated/dist/src/RCS/snmp.c,v 2.1 92/02/24 14:13:02 jch Exp $
*/
/*%Copyright%*/
/************************************************************************
* *
* GateD, Release 2 *
* *
* Copyright (c) 1990,1991,1992 by Cornell University *
* All rights reserved. *
* *
* THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY *
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT *
* LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY *
* AND FITNESS FOR A PARTICULAR PURPOSE. *
* *
* Royalty-free licenses to redistribute GateD Release *
* 2 in whole or in part may be obtained by writing to: *
* *
* GateDaemon Project *
* Information Technologies/Network Resources *
* 143 Caldwell Hall *
* Cornell University *
* Ithaca, NY 14853-2602 *
* *
* GateD is based on Kirton's EGP, UC Berkeley's routing *
* daemon (routed), and DCN's HELLO routing Protocol. *
* Development of Release 2 has been supported by the *
* National Science Foundation. *
* *
* Please forward bug fixes, enhancements and questions to the *
* gated mailing list: gated-people@gated.cornell.edu. *
* *
* Authors: *
* *
* Jeffrey C Honig <jch@gated.cornell.edu> *
* Scott W Brim <swb@gated.cornell.edu> *
* *
*************************************************************************
* *
* Portions of this software may fall under the following *
* copyrights: *
* *
* Copyright (c) 1988 Regents of the University of California. *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms are *
* permitted provided that the above copyright notice and *
* this paragraph are duplicated in all such forms and that *
* any documentation, advertising materials, and other *
* materials related to such distribution and use *
* acknowledge that the software was developed by the *
* University of California, Berkeley. The name of the *
* University may not be used to endorse or promote *
* products derived from this software without specific *
* prior written permission. THIS SOFTWARE IS PROVIDED *
* ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, *
* INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
* *
************************************************************************/
#if defined(AGENT_SNMP)
#include "include.h"
#include "snmp.h"
#include <snmp.h>
#include "egp.h"
static int snmp_request_next; /* Look at lexically next object */
static int snmp_request_object; /* Return object identifier also */
static int snmp_request_set; /* Request is to set variable */
bits snmp_types[] =
{
{AGENT_REG, "Register"},
{AGENT_REQ, "Request"},
{AGENT_ERR, "Error"},
{AGENT_RSP, "Response"},
{AGENT_REQN, "RequestNextObject"},
{AGENT_REQO, "RequestObject"},
{AGENT_RSPO, "ResponseObject"},
{AGENT_TRAP, "TrapRequest"},
{AGENT_SET, "SetRequest"},
{AGENT_QUERY, "Query"},
{AGENT_REGSET, "RegisterSet"},
{0, 0}
};
bits snmp_errors[] =
{
{NOERR, "noError"},
{TOOBIG, "tooBig"},
{NOSUCH, "noSuchName"},
{BADVAL, "badValue"},
{RDONLY, "readOnly",},
{GENERRS, "genErr",},
{0, 0}
};
int doing_snmp = TRUE;
static task *snmp_task = (task *) 0;
static int ipRoute();
#define ipRoutePrefix 1, 3, 6, 1, 2, 1, 4, 21, 1
#define ipRouteDest 1
#define ipRouteIfIndex 2
#define ipRouteMetric1 3
#define ipRouteMetric2 4
#define ipRouteMetric3 5
#define ipRouteMetric4 6
#define ipRouteNextHop 7
#define ipRouteType 8
#define ipRouteProto 9
#define ipRouteAge 10
#define ipRouteMask 11
#define ipRouteMetric5 12
#define ipRouteInfo 13
#ifdef PROTO_EGP
static int egp();
#define egpPrefix 1, 3, 6, 1, 2, 1, 8
#define egpInMsgs 1
#define egpInErrors 2
#define egpOutMsgs 3
#define egpOutErrors 4
#define egpAs 6
static int egpNeigh();
#define egpNeighPrefix 5, 1
#define egpNeighState 1
#define egpNeighAddr 2
#define egpNeighAs 3
#define egpNeighInMsgs 4
#define egpNeighInErrs 5
#define egpNeighOutMsgs 6
#define egpNeighOutErrs 7
#define egpNeighInErrMsgs 8
#define egpNeighOutErrMsgs 9
#define egpNeighStateUps 10
#define egpNeighStateDowns 11
#define egpNeighIntervalHello 12
#define egpNeighIntervalPoll 13
#define egpNeighMode 14
#define egpNeighEventTrigger 15
#endif /* PROTO_EGP */
static struct mibtbl snmptbl[] =
{
0,
{ipRoutePrefix, ipRouteDest}, 0, ipRoute, "ipRouteDest",
0,
{ipRoutePrefix, ipRouteIfIndex}, 0, ipRoute, "ipRouteIfIndex",
0,
{ipRoutePrefix, ipRouteMetric1}, 0, ipRoute, "ipRouteMetric1",
0,
{ipRoutePrefix, ipRouteMetric2}, 0, ipRoute, "ipRouteMetric2",
0,
{ipRoutePrefix, ipRouteMetric3}, 0, ipRoute, "ipRouteMetric3",
0,
{ipRoutePrefix, ipRouteMetric4}, 0, ipRoute, "ipRouteMetric4",
0,
{ipRoutePrefix, ipRouteNextHop}, 0, ipRoute, "ipRouteNextHop",
0,
{ipRoutePrefix, ipRouteType}, 0, ipRoute, "ipRouteType",
0,
{ipRoutePrefix, ipRouteProto}, 0, ipRoute, "ipRouteProto",
0,
{ipRoutePrefix, ipRouteAge}, 0, ipRoute, "ipRouteAge",
0,
{ipRoutePrefix, ipRouteMask}, 0, ipRoute, "ipRouteMask",
0,
{ipRoutePrefix, ipRouteMetric5}, 0, ipRoute, "ipRouteMetric5",
#ifdef PROTO_EGP
0,
{egpPrefix, egpInMsgs}, MIBF_ONLY, egp, "egpInMsgs",
0,
{egpPrefix, egpInErrors}, MIBF_ONLY, egp, "egpInErrors",
0,
{egpPrefix, egpOutMsgs}, MIBF_ONLY, egp, "egpOutMsgs",
0,
{egpPrefix, egpOutErrors}, MIBF_ONLY, egp, "egpOutErrors",
0,
{egpPrefix, egpNeighPrefix, egpNeighState}, 0, egpNeigh, "egpNeighState",
0,
{egpPrefix, egpNeighPrefix, egpNeighAddr}, 0, egpNeigh, "egpNeighAddr",
0,
{egpPrefix, egpNeighPrefix, egpNeighAs}, 0, egpNeigh, "egpNeighAs",
0,
{egpPrefix, egpNeighPrefix, egpNeighInMsgs}, 0, egpNeigh, "egpNeighInMsgs",
0,
{egpPrefix, egpNeighPrefix, egpNeighInErrs}, 0, egpNeigh, "egpNeighInErrs",
0,
{egpPrefix, egpNeighPrefix, egpNeighOutMsgs}, 0, egpNeigh, "egpNeighOutMsgs",
0,
{egpPrefix, egpNeighPrefix, egpNeighOutErrs}, 0, egpNeigh, "egpNeighOutErrs",
0,
{egpPrefix, egpNeighPrefix, egpNeighInErrMsgs}, 0, egpNeigh, "egpNeighInErrMsgs",
0,
{egpPrefix, egpNeighPrefix, egpNeighOutErrMsgs}, 0, egpNeigh, "egpNeighOutErrMsgs",
0,
{egpPrefix, egpNeighPrefix, egpNeighStateUps}, 0, egpNeigh, "egpNeighStateUps",
0,
{egpPrefix, egpNeighPrefix, egpNeighStateDowns}, 0, egpNeigh, "egpNeighStateDowns",
0,
{egpPrefix, egpNeighPrefix, egpNeighIntervalHello}, 0, egpNeigh, "egpNeighIntervalHello",
0,
{egpPrefix, egpNeighPrefix, egpNeighIntervalPoll}, 0, egpNeigh, "egpNeighIntervalPoll",
0,
{egpPrefix, egpNeighPrefix, egpNeighMode}, 0, egpNeigh, "egpNeighMode",
0,
{egpPrefix, egpNeighPrefix, egpNeighEventTrigger}, 0, egpNeigh, "egpNeighEventTrigger",
0,
{egpPrefix, egpAs}, MIBF_ONLY, egp, "egpAs",
#endif /* PROTO_EGP */
0,
{0}, 0, 0, 0,
};
/*
* Trace an SNMP or SGMP packet.
*/
static void
snmp_trace(tp, direction, packet, length)
task *tp;
char *direction;
char *packet;
int length;
{
int size, type, integer, i;
const char *cp;
char *pkt = packet;
char comment[MAXHOSTNAMELENGTH];
struct sockaddr_in addr;
struct mibtbl *mib_ptr;
(void) sprintf(comment, "%s %s", tp->task_name, direction);
cp = trace_state(snmp_types, (*pkt) - 1);
if (!cp) {
cp = "Unknown";
}
tracef("%s %#A socket %d type %s(%d) length %d",
comment,
&tp->task_addr,
tp->task_socket,
cp, *pkt++, length);
if (trace_flags & TR_UPDATE) {
if ((pkt - packet) <= length) {
switch (*packet) {
case AGENT_TRAP:
trace(TR_SNMP, 0, NULL);
type = *pkt++;
size = *pkt++;
trace(TR_SNMP, 0, "%s\ttrap type %1d",
comment,
type);
tracef("%s\tlength %2d variable: ",
comment,
size);
for (i = 0; i < size; i++) {
tracef("%s%d", i ? "." : "", *pkt++ & 0xff);
}
trace(TR_SNMP, 0, NULL);
/* Fall through to display variables */
case AGENT_RSPO:
case AGENT_RSP:
if (*packet != AGENT_TRAP) {
trace(TR_SNMP, 0, NULL);
}
while ((pkt - packet) <= length - 1) {
switch (*pkt++) {
case INT:
size = *pkt++;
memcpy((char *) &integer, pkt, size);
pkt += size;
trace(TR_SNMP, 0, "%s\tinteger length %d value: %d %#x", comment, size, integer, integer);
break;
case STR:
size = *pkt++;
tracef("%s\tstring length %d value: ", comment, size);
for (; size; size--) {
tracef("%c", *pkt++);
}
trace(TR_SNMP, 0, NULL);
break;
case IPADD:
size = *pkt++;
sockclear_in(&addr);
memcpy((char *) &addr.sin_addr, pkt, size);
pkt += size;
trace(TR_SNMP, 0, "%s\tIP address length %d value: %A %#x",
comment,
size,
&addr,
addr.sin_addr.s_addr);
break;
case CNTR:
size = *pkt++;
memcpy((char *) &integer, pkt, size);
pkt += size;
trace(TR_SNMP, 0, "%s\tcounter length %d value: %u %#x", comment, size, integer, integer);
break;
case GAUGE:
size = *pkt++;
memcpy((char *) &integer, pkt, size);
pkt += size;
trace(TR_SNMP, 0, "%s\tgauge length %d value: %u %#x", comment, size, integer, integer);
break;
case TIME:
size = *pkt++;
memcpy((char *) &integer, pkt, size);
pkt += size;
trace(TR_SNMP, 0, "%s\ttimer length %d value: %u %#x", comment, size, integer, integer);
break;
}
}
break;
case AGENT_ERR:
if ((pkt - packet) < length) {
cp = trace_state(snmp_errors, *pkt);
if (!cp) {
cp = "???";
}
trace(TR_SNMP, 0, " error %s(%d)",
cp, *pkt);
}
break;
case AGENT_REQ:
case AGENT_REG:
case AGENT_REQO:
case AGENT_REQN:
trace(TR_SNMP, 0, NULL);
while ((pkt - packet) <= length - 1) {
size = *pkt++;
for (mib_ptr = (struct mibtbl *) tp->task_data; mib_ptr->function; mib_ptr++) {
if (size < mib_ptr->length) {
continue;
}
if (!memcmp(pkt, mib_ptr->object, mib_ptr->length)) {
tracef("%s\t%s",
comment,
mib_ptr->name);
pkt += mib_ptr->length;
for (i = mib_ptr->length; i < size; i++) {
tracef(".%d", *pkt++ & 0xff);
}
trace(TR_SNMP, 0, NULL);
break;
}
}
if (!mib_ptr->function) {
tracef("%s\tlength %2d variable: ",
comment,
size);
for (i = 0; i < size; i++) {
tracef("%s%d", i ? "." : "", *pkt++ & 0xff);
}
trace(TR_SNMP, 0, NULL);
}
}
break;
}
}
} else {
trace(TR_SNMP, 0, NULL);
}
trace(TR_SNMP, 0, NULL);
}
/*
* Send and trace an SNMP packet
*/
static void
snmp_send(tp, packet, size)
task *tp;
char *packet;
int size;
{
TRACE_SNMPPKT(tp, "SEND", packet, size);
(void) task_send_packet(tp,
packet,
size,
0,
(sockaddr_un *) 0);
return;
}
/*
* Register all of our supported variables with SNMPD.
*/
/*ARGSUSED*/
static int
snmp_register(tp, p, write_only)
task *tp;
char *p;
flag_t write_only;
{
int asize;
struct mibtbl *mib_ptr;
*p++ = write_only ? AGENT_REGSET : AGENT_REG;
asize = 1;
for (mib_ptr = (struct mibtbl *) tp->task_data; mib_ptr->function; mib_ptr++) {
if (!write_only || (mib_ptr->flags & MIBF_WRITE)) {
*p++ = mib_ptr->length;
memcpy(p, mib_ptr->object, mib_ptr->length);
#ifdef notdef
if (mib_ptr->flags & MIBF_WRITE) {
*(p - 1)++;
p[mib_ptr->length] = 0;
p++;
asize++;
}
#endif /* notdef */
p += mib_ptr->length;
asize += mib_ptr->length + 1;
}
}
return (asize);
}
/*
* Process an incoming request from SNMPD. Speed is of the essence here.
* Not elegance.
*/
static void
snmp_recv(tp)
task *tp;
{
int size;
char agntreqpkt[SNMPMAXPKT];
char *ptr = recv_iovec[RECV_IOVEC_DATA].iov_base;
char *ptr1 = agntreqpkt;
int error = 0;
int retsize;
int rspsize = 0, reqsize;
struct mibtbl *mib_ptr;
if (task_receive_packet(tp, &size)) {
return;
}
TRACE_SNMPPKT(tp, "RECV", ptr, size);
snmp_request_next = FALSE;
snmp_request_object = FALSE;
snmp_request_set = FALSE;
switch (*ptr) {
case AGENT_REG:
case AGENT_RSP:
case AGENT_ERR:
case AGENT_RSPO:
case AGENT_TRAP:
trace(TR_ALL, LOG_ERR, "snmp_recv: unexpected AGENT packet type");
return;
case AGENT_REQN:
snmp_request_next = TRUE;
case AGENT_REQO:
snmp_request_object = TRUE;
case AGENT_SET:
if (*ptr == AGENT_SET) {
snmp_request_set = TRUE;
}
case AGENT_REQ:
if (snmp_request_object) {
*ptr1++ = AGENT_RSPO;
/* Setup space for returned object identifier */
ASN_SET_TYPE(ptr1, IPADD);
ASN_SET_LENGTH(ptr1, sizeof(struct in_addr));
rspsize = ASN_LENGTH(ptr1) + 1;
ASN_INCR(ptr1);
} else {
*ptr1++ = AGENT_RSP;
rspsize = 1;
}
ptr++;
reqsize = *ptr++;
for (mib_ptr = (struct mibtbl *) tp->task_data; mib_ptr->function; mib_ptr++) {
if (mib_ptr->length > reqsize) {
continue;
}
if (memcmp(ptr, mib_ptr->object, mib_ptr->length) == 0) {
break;
}
}
if (mib_ptr->function) {
ptr += mib_ptr->length;
if (!mib_ptr->function) {
/* No function for this variable */
error++;
retsize = NOSUCH;
} else if (snmp_request_set && !(mib_ptr->flags & MIBF_WRITE)) {
/* Variable is not writable */
error++;
retsize = RDONLY;
}
if ((retsize = (mib_ptr->function) (mib_ptr->object[mib_ptr->length - 1],
ptr,
ptr1,
reqsize - mib_ptr->length)) <= 0) {
error++;
if (retsize < 0) {
/* Error code is returned negative */
retsize = -retsize;
} else {
/* No error - assume generic */
retsize = -GENERRS;
}
} else {
rspsize += retsize;
}
}
if (error) {
agntreqpkt[0] = AGENT_ERR;
agntreqpkt[1] = retsize;
rspsize = 2;
}
break;
case AGENT_QUERY:
rspsize = snmp_register(tp, agntreqpkt, TRUE);
break;
default:
trace(TR_SNMP, LOG_ERR, "snmp_recv: invalid AGENT packet type");
agntreqpkt[0] = AGENT_ERR;
rspsize = 1;
break;
} /* switch */
snmp_send(tp, agntreqpkt, rspsize);
return;
}
/*
* Register all of our supported variables with SNMPD.
*/
/*ARGSUSED*/
static void
snmp_job(tip, interval)
timer *tip;
time_t interval;
{
int size;
char agntpkt[SNMPMAXPKT];
size = snmp_register(tip->timer_task, agntpkt, FALSE);
snmp_send(tip->timer_task, agntpkt, size);
}
static void
snmp_terminate(tp)
task *tp;
{
snmp_task = (task *) 0;
task_delete(tp);
}
static int
ipRoute(object, src, dst, size)
int object;
char *src, *dst;
int size;
{
int integer;
rt_entry *rt = 0;
if (!size && snmp_request_object) {
rt = rt_next((sockaddr_un *) 0);
} else if (size == sizeof(struct in_addr)) {
struct sockaddr_in dest;
sockclear_in(&dest);
memcpy((char *) &dest.sin_addr, src, size);
if (snmp_request_next) {
rt = rt_next((sockaddr_un *) & dest);
} else {
rt = rt_lookup(RTS_NETROUTE | RTS_HOSTROUTE, (sockaddr_un *) & dest);
if (!rt && (dest.sin_addr.s_addr == (u_long) DEFAULTNET)) {
rt = rt_next((sockaddr_un *) & dest);
}
}
}
if (!rt) {
return (-NOSUCH);
}
if (snmp_request_object) {
ASN_SET_VALUE((dst - sizeof(long) - 2), &rt->rt_dest.in.sin_addr);
}
switch (object) {
case ipRouteDest:
ASN_SET_TYPE(dst, IPADD);
ASN_SET_LENGTH(dst, sizeof(rt->rt_dest.in.sin_addr));
ASN_SET_VALUE(dst, &rt->rt_dest.in.sin_addr);
break;
case ipRouteIfIndex:
integer = rt->rt_ifp->int_index;
ASN_SET_TYPE(dst, INT);
ASN_SET_LENGTH(dst, sizeof(integer));
ASN_SET_VALUE(dst, &integer);
break;
case ipRouteMetric1:
integer = rt->rt_metric;
ASN_SET_TYPE(dst, INT);
ASN_SET_LENGTH(dst, sizeof(integer));
ASN_SET_VALUE(dst, &integer);
break;
case ipRouteMetric2:
case ipRouteMetric3:
case ipRouteMetric4:
case ipRouteMetric5:
integer = -1;
ASN_SET_TYPE(dst, INT);
ASN_SET_LENGTH(dst, sizeof(integer));
ASN_SET_VALUE(dst, &integer);
break;
case ipRouteNextHop:
ASN_SET_TYPE(dst, IPADD);
ASN_SET_LENGTH(dst, sizeof(rt->rt_router.in.sin_addr));
ASN_SET_VALUE(dst, &rt->rt_router.in.sin_addr);
break;
case ipRouteType:
if (rt->rt_state & RTS_HOLDDOWN) {
integer = 2;
} else {
switch (rt->rt_proto) {
case RTPROTO_DIRECT:
integer = 3;
break;
default:
integer = 4;
}
}
ASN_SET_TYPE(dst, INT);
ASN_SET_LENGTH(dst, sizeof(integer));
ASN_SET_VALUE(dst, &integer);
break;
case ipRouteProto:
switch (rt->rt_proto) {
case RTPROTO_RIP:
integer = 8;
break;
case RTPROTO_HELLO:
integer = 7;
break;
case RTPROTO_EGP:
integer = 5;
break;
case RTPROTO_DIRECT:
integer = 1;
break;
case RTPROTO_REDIRECT:
integer = 4;
break;
case RTPROTO_DEFAULT:
integer = 2;
break;
case RTPROTO_IGP:
integer = 9;
break;
case RTPROTO_IGRP:
integer = 11;
break;
case RTPROTO_OSPF:
integer = 13;
break;
case RTPROTO_BGP:
integer = 14;
break;
case RTPROTO_STATIC:
integer = 2;
break;
default:
integer = 1;
}
ASN_SET_TYPE(dst, INT);
ASN_SET_LENGTH(dst, sizeof(integer));
ASN_SET_VALUE(dst, &integer);
break;
case ipRouteAge:
integer = rt->rt_timer;
ASN_SET_TYPE(dst, INT);
ASN_SET_LENGTH(dst, sizeof(integer));
ASN_SET_VALUE(dst, &integer);
break;
case ipRouteMask:
ASN_SET_TYPE(dst, IPADD);
ASN_SET_LENGTH(dst, sizeof(rt->rt_dest_mask.in.sin_addr));
ASN_SET_VALUE(dst, &rt->rt_dest_mask.in.sin_addr);
break;
default:
return (-NOSUCH);
}
return (ASN_LENGTH(dst));
}
/*ARGSUSED*/
static int
egp(object, src, dst, size)
int object;
char *src, *dst;
u_int size;
{
u_int counter;
int integer;
if (size) {
return (-NOSUCH);
}
if (!(doing_egp)) {
return (-NOSUCH);
}
switch (object) {
case egpInMsgs:
counter = egp_stats.inmsgs;
ASN_SET_TYPE(dst, CNTR);
ASN_SET_LENGTH(dst, sizeof(counter));
ASN_SET_VALUE(dst, &counter);
break;
case egpInErrors:
counter = egp_stats.inerrors;
ASN_SET_TYPE(dst, CNTR);
ASN_SET_LENGTH(dst, sizeof(counter));
ASN_SET_VALUE(dst, &counter);
break;
case egpOutMsgs:
counter = egp_stats.outmsgs;
ASN_SET_TYPE(dst, CNTR);
ASN_SET_LENGTH(dst, sizeof(counter));
ASN_SET_VALUE(dst, &counter);
break;
case egpOutErrors:
counter = egp_stats.outerrors;
ASN_SET_TYPE(dst, CNTR);
ASN_SET_LENGTH(dst, sizeof(counter));
ASN_SET_VALUE(dst, &counter);
break;
case egpAs:
integer = my_system;
ASN_SET_TYPE(dst, INT);
ASN_SET_LENGTH(dst, sizeof(integer));
ASN_SET_VALUE(dst, &integer);
break;
default:
return (-NOSUCH);
}
return (ASN_LENGTH(dst));
}
static int
egpNeigh(object, src, dst, size)
int object;
char *src, *dst;
int size;
{
int neighbor = egp_neighbors;
int integer;
u_int counter;
struct egpngh *ngp;
if (!(doing_egp)) {
return (-NOSUCH);
}
if (!size && snmp_request_next) {
neighbor = 0;
} else if (size == sizeof(struct in_addr)) {
struct sockaddr_in dest;
sockclear_in(&dest);
memcpy((char *) &dest.sin_addr, src, size);
if (dest.sin_addr.s_addr != (u_long) DEFAULTNET) {
for (neighbor = 0; neighbor < egp_neighbors; neighbor++) {
if (equal(&egp_sort[neighbor]->ng_addr, &dest.sin_addr)) {
break;
}
}
if (snmp_request_next) {
neighbor++;
}
} else {
neighbor = snmp_request_next ? 0 : egp_neighbors;
}
}
if (neighbor >= egp_neighbors) {
return (-NOSUCH);
}
ngp = egp_sort[neighbor];
if (snmp_request_object) {
ASN_SET_VALUE((dst - sizeof(ngp->ng_addr.sin_addr) - 2), &ngp->ng_addr.sin_addr);
}
switch (object) {
case egpNeighState:
integer = ngp->ng_state + 1;
ASN_SET_TYPE(dst, INT);
ASN_SET_LENGTH(dst, sizeof(integer));
ASN_SET_VALUE(dst, &integer);
break;
case egpNeighAddr:
ASN_SET_TYPE(dst, IPADD);
ASN_SET_LENGTH(dst, sizeof(ngp->ng_addr.sin_addr));
ASN_SET_VALUE(dst, &ngp->ng_addr.sin_addr);
break;
case egpNeighAs:
integer = ngp->ng_asin;
ASN_SET_TYPE(dst, INT);
ASN_SET_LENGTH(dst, sizeof(integer));
ASN_SET_VALUE(dst, &integer);
break;
case egpNeighInMsgs:
counter = ngp->ng_stats.inmsgs;
ASN_SET_TYPE(dst, CNTR);
ASN_SET_LENGTH(dst, sizeof(counter));
ASN_SET_VALUE(dst, &counter);
break;
case egpNeighInErrs:
counter = ngp->ng_stats.inerrors;
ASN_SET_TYPE(dst, CNTR);
ASN_SET_LENGTH(dst, sizeof(counter));
ASN_SET_VALUE(dst, &counter);
break;
case egpNeighOutMsgs:
counter = ngp->ng_stats.outmsgs;
ASN_SET_TYPE(dst, CNTR);
ASN_SET_LENGTH(dst, sizeof(counter));
ASN_SET_VALUE(dst, &counter);
break;
case egpNeighOutErrs:
counter = ngp->ng_stats.outerrors;
ASN_SET_TYPE(dst, CNTR);
ASN_SET_LENGTH(dst, sizeof(counter));
ASN_SET_VALUE(dst, &counter);
break;
case egpNeighInErrMsgs:
counter = ngp->ng_stats.inerrmsgs;
ASN_SET_TYPE(dst, CNTR);
ASN_SET_LENGTH(dst, sizeof(counter));
ASN_SET_VALUE(dst, &counter);
break;
case egpNeighOutErrMsgs:
counter = ngp->ng_stats.outerrmsgs;
ASN_SET_TYPE(dst, CNTR);
ASN_SET_LENGTH(dst, sizeof(counter));
ASN_SET_VALUE(dst, &counter);
break;
case egpNeighStateUps:
counter = ngp->ng_stats.stateups;
ASN_SET_TYPE(dst, CNTR);
ASN_SET_LENGTH(dst, sizeof(counter));
ASN_SET_VALUE(dst, &counter);
break;
case egpNeighStateDowns:
counter = ngp->ng_stats.statedowns;
ASN_SET_TYPE(dst, CNTR);
ASN_SET_LENGTH(dst, sizeof(counter));
ASN_SET_VALUE(dst, &counter);
break;
case egpNeighIntervalHello:
integer = ngp->ng_T1;
ASN_SET_TYPE(dst, INT);
ASN_SET_LENGTH(dst, sizeof(integer));
ASN_SET_VALUE(dst, &integer);
break;
case egpNeighIntervalPoll:
integer = ngp->ng_T2;
ASN_SET_TYPE(dst, INT);
ASN_SET_LENGTH(dst, sizeof(integer));
ASN_SET_VALUE(dst, &integer);
break;
case egpNeighMode:
integer = ngp->ng_M;
ASN_SET_TYPE(dst, INT);
ASN_SET_LENGTH(dst, sizeof(integer));
ASN_SET_VALUE(dst, &integer);
break;
#define egpNeighEventTriggerStart 1
#define egpNeighEventTriggerStop 2
case egpNeighEventTrigger:
if (!ngp->ng_stats.trigger) {
ngp->ng_stats.trigger = egpNeighEventTriggerStop;
}
integer = ngp->ng_stats.trigger;
ASN_SET_TYPE(dst, INT);
ASN_SET_LENGTH(dst, sizeof(integer));
ASN_SET_VALUE(dst, &integer);
break;
}
return (ASN_LENGTH(dst));
}
static void
snmp_trap(trap, ptr)
int trap;
char *ptr;
{
int i;
struct egpngh *ngp = (struct egpngh *) ptr;
if_entry *ifp = (if_entry *) ptr;
static objident ifIndex =
{10,
{1, 3, 6, 1, 2, 1, 2, 2, 1, 1}};
static objident egpNeighAddrObj =
{10,
{1, 3, 6, 1, 2, 1, 8, 5, 1, 2}};
objident *obj_ptr;
char *val_ptr;
int val_size;
int val_type;
char trap_pkt[SNMPMAXPKT];
int trap_size = 0;
char *trap_ptr = trap_pkt;
if (!snmp_task) {
/* Return if SNMP not active */
return;
}
switch (trap) {
case LINKDOWN:
case LINKUP:
obj_ptr = &ifIndex;
val_ptr = (char *) &ifp->int_index;
val_size = 1;
val_type = INT;
break;
case EGPNHBRLOST:
obj_ptr = &egpNeighAddrObj;
val_ptr = (char *) &ngp->ng_addr;
val_size = sizeof(ngp->ng_addr);
val_type = IPADD;
break;
default:
trace(TR_SNMP, LOG_ERR, "snmp_trap: Unknown SNMP trap type: %d", trap);
return;
}
*trap_ptr++ = AGENT_TRAP;
ASN_SET_TYPE(trap_ptr, trap);
ASN_SET_LENGTH(trap_ptr, obj_ptr->ncmp + val_size);
for (i = 0; i < obj_ptr->ncmp; i++) {
trap_ptr[i + 2] = obj_ptr->cmp[i] & 0xff;
}
memcpy(&trap_ptr[obj_ptr->ncmp + 2], (char *) val_ptr, val_size);
ASN_INCR(trap_ptr);
ASN_SET_TYPE(trap_ptr, val_type);
ASN_SET_LENGTH(trap_ptr, val_size);
ASN_SET_VALUE(trap_ptr, val_ptr);
ASN_INCR(trap_ptr);
trap_size = trap_ptr - trap_pkt;
snmp_send(snmp_task, trap_pkt, trap_size);
return;
}
void
snmp_trap_egpNeighborLoss(ngp)
struct egpngh *ngp;
{
snmp_trap(EGPNHBRLOST, (char *) ngp);
}
/*ARGSUSED*/
static void
snmp_trap_ifchange(tp, ifp)
task *tp;
if_entry *ifp;
{
snmp_trap((ifp->int_state & IFS_UP) ? LINKUP : LINKDOWN, (char *) ifp);
}
void
snmp_init()
{
struct mibtbl *mib_ptr = snmptbl;
if (!doing_snmp) {
if (snmp_task) {
snmp_terminate(snmp_task);
}
return;
} else if (snmp_task) {
return;
}
snmp_task = task_alloc("SNMP");
sockclear_in(&snmp_task->task_addr.in);
snmp_task->task_addr.in.sin_port = htons(AGENT_SNMP_PORT);
snmp_task->task_addr.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
snmp_task->task_recv = snmp_recv;
snmp_task->task_terminate = snmp_terminate;
snmp_task->task_ifchange = snmp_trap_ifchange;
snmp_task->task_data = (caddr_t) mib_ptr;
if ((snmp_task->task_socket = task_get_socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
quit(errno);
}
if (!task_create(snmp_task, SNMPMAXPKT)) {
quit(EINVAL);
}
if (task_set_option(snmp_task, TASKOPTION_RECVBUF, (caddr_t) (32 * 1024)) < 0) {
quit(errno);
}
if (task_set_option(snmp_task, TASKOPTION_DONTROUTE, (caddr_t) TRUE) < 0) {
quit(errno);
}
if (!test_flag) {
struct sockaddr_in addr;
sockclear_in(&addr);
addr.sin_port = 0;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(snmp_task->task_socket, (struct sockaddr *) & addr, socksize(&addr)) < 0) {
trace(TR_ALL, LOG_ERR, "snmp_init: bind: %m");
quit(errno);
}
if (connect(snmp_task->task_socket, &snmp_task->task_addr.a, socksize(&snmp_task->task_addr.a)) < 0) {
trace(TR_ALL, LOG_ERR, "snmp_init: connect: %m");
quit(errno);
}
}
(void) timer_create(snmp_task, 0, "Register", 0, (time_t) SNMP_REGISTER_INTERVAL, snmp_job);
for (; mib_ptr->function; mib_ptr++) {
if (!mib_ptr->length) {
mib_ptr->length = strlen(mib_ptr->object);
}
}
}
#endif /* AGENT_SNMP */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.