Files
m241Neelima/vxworks-6.9/target/src/wrn/wm/snmp/engine/proxy.c
T
2026-07-30 11:19:44 +05:30

561 lines
17 KiB
C

/*
* Copyright 2000-2005 Wind River Systems, Inc.
* All rights reserved. Provided under license only.
* Distribution or other use of this software is only
* permitted pursuant to the terms of a license agreement
* from Wind River Systems (and is otherwise prohibited).
* Refer to that license agreement for terms of use.
*/
/*
* Copyright 1995-1997 Epilogue Technology Corporation.
* Copyright 1998 Integrated Systems, Inc.
* All rights reserved.
*/
/*
* $Log: proxy.c,v $
* Revision 1.4 2003/01/15 14:05:06 josh
* directory structure shifting
*
* Revision 1.3 2001/11/06 21:50:48 josh
* second (and hopefully final) pass of new path hacking
*
* Revision 1.2 2001/11/06 21:20:19 josh
* revised new path hacking
*
* Revision 1.1.1.1 2001/11/05 17:47:41 tneale
* Tornado shuffle
*
* Revision 9.5 2001/01/19 22:22:23 paul
* Update copyright.
*
* Revision 9.4 2000/03/17 00:19:15 meister
* Update copyright message
*
* Revision 9.3 1999/12/23 14:47:30 josh
* cleaning up code per Shawn's comments -- removing extraneous
* comments and doing proxy check before notify check
*
* Revision 9.2 1999/11/01 19:56:54 josh
* cleaning up initializations to keep extra files out of code when not
* in use
*
* Revision 9.1 1998/11/30 21:07:53 sar
* Modified the timer code to use ENVOY_TIMER_32_Ts to make sure the 32 bit
* ids are properly aligned and saved.
*
* Revision 9.0 1998/10/16 22:11:51 sar
* Update version stamp to match release
*
* Revision 8.4 1998/08/12 04:43:56 sar
* Move the initialization routines around some in order to minimize
* the amount of code that gets pulled in for init purposes.
*
* Revision 8.3 1998/06/05 18:53:16 sra
* "#include <foo.h>" => "#include <envoy/h/foo.h>".
*
* Revision 8.2 1998/02/25 15:21:31 sra
* Finish moving types.h, bug.h, and bugdef.h to common/h/.
*
* Revision 8.1 1998/02/25 04:52:14 sra
* Update copyrights.
*
* Revision 8.0 1997/11/18 00:56:54 sar
* Updated revision to 8.0
*
* Revision 7.5 1997/11/01 01:25:36 sar
* In the packet we are processing save a pointer to the coarse lock we
* are using so that we can free it later without needing to know which
* lock it was.
*
* Revision 7.4 1997/10/22 03:10:29 sar
* Modified the installation options for agentx and the older sub agent scheme
*
* Also moved the allocation of the locks into envoy_init (env_init.c),
* so they can be initialized if necessary.
*
* Revision 7.3 1997/10/16 00:45:58 sar
* Updated for agentx support, with most of the work in mibutils.c to deal
* with interior leaves and the pdu processors to deal with agentx leaves,
* especially their reference counts.
*
* Add a bug macro into the get_{read write}_lock calls to give the user
* a chance if things start going wrong.
*
* Fixed a potential problem int the proxy code where we were trying to
* stuff a 32 bit quantity into a pointer which may or may not work depending
* on the platform.
*
* Revision 7.2 1997/03/20 06:49:06 sra
* DFARS-safe copyright text. Zap!
*
* Revision 7.1 1997/02/25 10:49:26 sra
* Update copyright notice, dust under the bed.
*
* Revision 7.0 1996/03/18 20:01:11 sar
* Updated revision to 7.0 and copyright to 96
*
* Revision 6.4 1996/02/27 00:02:24 sar
* Added test for large repsones to gets and get-nexts.
*
* Revision 6.3 1996/01/10 16:34:47 sar
* proper cast of proxy routines
*
* Revision 6.2 1995/11/14 22:44:42 sar
* Moved the translation routines to auxi/proxy_{v1 v2}
*
* Revision 6.1 1995/11/04 01:52:51 sar
* Basically rebuilt the code, this was necessitated by the
* demise of parties and the removal of the transport info
* that parties had carried.
* The proxy capability was also expanded to cover the v1 case
*
* Revision 6.0 1995/05/31 21:47:50 sra
* Release 6.0.
*
* Revision 1.5 1995/05/23 23:23:14 sar
* Clean up the response packet's ppc oids before overwriting tehm.
*
* Revision 1.4 1995/04/28 23:16:40 sar
* Changed tow of the loops that walk a linked list to use ** to walk
* down the links.
*
* Revision 1.3 1995/04/18 21:13:44 sar
* Use the new lock macros, added code to determine where to send v2 traps
* from a v1 soruce we are proxying for.
*
* Revision 1.2 1995/03/22 18:41:13 sar
* We now test that the pcb_root points to something before trying to
* use it as a pointer.
* Changed the method for sending packets from io_complete to
* ENVOY_Send_SNMP_Packet, to take advantage of the size checks.
*
* Revision 1.1 1995/03/21 00:09:23 sar
* Initial revision
*
*
*/
/* [clearcase]
modification history
-------------------
01b,18apr05,job update copyright notices
01a,24nov03,job update copyright information
*/
#include <wrn/wm/snmp/engine/asn1conf.h>
#include <wrn/wm/snmp/engine/asn1.h>
#include <wrn/wm/snmp/engine/snmpdefs.h>
#include <wrn/wm/snmp/engine/snmp.h>
#include <wrn/wm/snmp/engine/objectid.h>
#include <wrn/wm/snmp/engine/buffer.h>
#include <wrn/wm/snmp/engine/buildpkt.h>
#include <wrn/wm/snmp/engine/snmpstat.h>
#include <wrn/wm/snmp/engine/etimer.h>
#include <wrn/wm/snmp/engine/wkobj.h>
#include <wrn/wm/snmp/engine/proxy.h>
#include <wrn/wm/common/bug.h>
#if INSTALL_ENVOY_SNMP_PROXY
extern PROXY_CB_T *pcb_root;
extern UINT_32_T proxy_id;
void
Clean_PCB(PROXY_CB_T *pcb)
{
EBufferClean(&pcb->community);
SNMP_memory_free(pcb);
}
/****************************************************************************
NAME: SNMP_Proxy_Timer
PURPOSE: Routine to be called by the timer code to clean up the proxy
list on timeouts. The cookie is the index into the proxy
list we look up the index and remove the control block.
PARAMETERS:
struct envoy_timer * the timer control block
void * the cookie pointer
RETURNS: void
****************************************************************************/
void
SNMP_Proxy_Timer(ENVOY_TIMER_T *tm,
void *cookiep)
{
bits32_t reqid;
PROXY_CB_T *pcb = 0, **pcbp;
reqid = ((ENVOY_TIMER_32_T *)cookiep)->id;
#if INSTALL_ENVOY_SNMP_LOCK
/* We don't have any good options if we can't get the lock.
So we require the user to not do that, if they do we generate
a bug report and if they don't handle that we return which is
the least bad thing to do. */
if (ENVOY_SNMP_GET_WRITE_LOCK(SNMP_ProxyLock)) {
BUG(BUG_ENVOY_LOCKING, BUG_FATAL, 0,
(BUG_OUT, "SNMP_Proxy_Timer(): proxy lock is broken", 0));
return;
}
#endif
for(pcbp = &pcb_root; *pcbp; pcbp = &(*pcbp)->next)
if ((*pcbp)->indx == reqid) {
pcb = *pcbp;
*pcbp = pcb->next;
break;
}
ENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_ProxyLock);
/* if we found a structure clean it up */
if (pcb) {
pcb->err_comp(&pcb->for_addr, &pcb->loc_addr, 1, pcb->async_cookie);
Clean_PCB(pcb);
}
SNMP_memory_free(cookiep);
return;
}
/****************************************************************************
NAME: SNMP_Proxy_Request
PURPOSE: Provide proxy handling, we save state information and then
call the routine supplied by the transport structure to
do the actual proxy handling.
PARAMETERS:
SNMP_PKT_T * Packet we're working on
RETURNS: void
****************************************************************************/
void
SNMP_Proxy_Request(SNMP_PKT_T *pktp)
{
PROXY_CB_T *pcb;
ENVOY_TIMER_32_T *tm32;
UINT_32_T pid, old_reqid;
INT_32_T ttl;
/* Size checks. For sets and bulks we make sure that a response
packet will be smaller than the current max packet, any size restrictions
for other types will be handled by the packet sending routines. */
#if (INSTALL_ENVOY_SNMP_VERSION_2)
if ((pktp->pdu_type == GET_BULK_REQUEST_PDU) &&
(pktp->maxpkt < (25 + EBufferUsed(&pktp->community)))) {
SGRPv2_INC_COUNTER(snmp_stats.snmpSilentDrops);
pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst, 1,
pktp->async_cookie);
return;
}
if ((pktp->snmp_version != SNMP_VERSION_1) &&
(pktp->pdu_type == SET_REQUEST_PDU) &&
((SNMP_Bufsize_For_Packet(pktp) + 4) > pktp->maxpkt)) {
ENVOY_Send_SNMP_Error_Packet(pktp, TOO_BIG, 0);
return;
}
#endif
/* Attempt to get the proxy id, we need to lock it (in a reentrent system)
to make sure the proxy ids are unique */
#if (INSTALL_ENVOY_SNMP_LOCK)
if (ENVOY_SNMP_GET_WRITE_LOCK(SNMP_ProxyLock)) {
BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0,
(BUG_OUT, "SNMP_Proxy_Request: proxy lock broken", 0));
ENVOY_Send_SNMP_Error_Packet(pktp, GEN_ERR, 0);
return;
}
#endif
pid = proxy_id++;
ENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_ProxyLock);
/* save the old reqid for later and install the new reqid,
then try and send the packet */
old_reqid = pktp->pdu.std_pdu.request_id;
pktp->pdu.std_pdu.request_id = pid;
ttl = ((INT_32_T (*) __((SNMP_PKT_T *)))(pktp->proxy_routine))(pktp);
/* restore the old reqid in case we need to send an error packet */
pktp->pdu.std_pdu.request_id = old_reqid;
/* If the proxy routine failed we send out an error */
if (ttl < 0) {
ENVOY_Send_SNMP_Error_Packet(pktp, GEN_ERR, 0);
return;
}
/* Acquire the space for the proxy state block and the timer block */
if ((pcb = (PROXY_CB_T *)SNMP_memory_alloc(sizeof(PROXY_CB_T))) == 0) {
ENVOY_Send_SNMP_Error_Packet(pktp, GEN_ERR, 0);
return;
}
EBufferInitialize(&pcb->community);
tm32 = (ENVOY_TIMER_32_T *)SNMP_memory_alloc(sizeof(ENVOY_TIMER_32_T));
if (tm32 == 0) {
Clean_PCB(pcb);
ENVOY_Send_SNMP_Error_Packet(pktp, GEN_ERR, 0);
return;
}
/* Move the community string from the packet structure
to the proxy block structure. This code resets the
packet flags to STATIC because the ownership now
rests with the proxy block structure. */
EBufferPreLoad(pktp->community.bflags, &pcb->community,
EBufferStart(&pktp->community),
EBufferUsed(&pktp->community));
pktp->community.bflags = BFL_IS_STATIC;
pcb->indx = pid;
pcb->reqid = old_reqid;
MEMCPY(&pcb->loc_addr, &pktp->pkt_dst, sizeof(SNMPADDR_T));
MEMCPY(&pcb->for_addr, &pktp->pkt_src, sizeof(SNMPADDR_T));
pcb->io_comp = pktp->io_complete;
pcb->err_comp = pktp->error_complete;
pcb->async_cookie = pktp->async_cookie;
pcb->maxpkt = pktp->maxpkt;
pcb->pdu_type = pktp->pdu_type;
pcb->original_version = pktp->snmp_version;
/* We need to get the proxy lock before trying to install the timer and pcb
blocks into their proper lists */
#if (INSTALL_ENVOY_SNMP_LOCK)
if (ENVOY_SNMP_GET_WRITE_LOCK(SNMP_ProxyLock)) {
BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0,
(BUG_OUT, "SNMP_Proxy_Request: proxy lock broken", 0));
ENVOY_Send_SNMP_Error_Packet(pktp, GEN_ERR, 0);
Clean_PCB(pcb);
SNMP_memory_free(tm32);
return;
}
#endif
/* attempt to set up a timer to clean up the pcb if we don't get a response
packet, if we can't set up the timer remove the pcb and send an error
packet */
envoy_tm_init(&(tm32->timer));
tm32->id = pcb->indx;
tm32->timer.cookie = tm32;
tm32->timer.handler = SNMP_Proxy_Timer;
if (envoy_tm_set(&(tm32->timer), ttl)) {
ENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_ProxyLock);
ENVOY_Send_SNMP_Error_Packet(pktp, GEN_ERR, 0);
Clean_PCB(pcb);
SNMP_memory_free(tm32);
return;
}
/* We have succeeded in building all the right structures, attach
the pcb to the list */
pcb->next = pcb_root;
pcb_root = pcb;
ENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_ProxyLock);
return;
}
/****************************************************************************
NAME: SNMP_Proxy_Response
PURPOSE: Provide proxy handling, attempt to restore the saved state
and transmit a response packet to the original request.
PARAMETERS:
SNMP_PKT_T * Packet we're working on
RETURNS: 0 if successfully processed packet, 1 otherwise
****************************************************************************/
int
SNMP_Proxy_Response(SNMP_PKT_T *pktp)
{
PROXY_CB_T *pcb = 0, **pcbp;
UINT_32_T reqid;
ALENGTH_T pktsize;
/* Dig out the saved state, and prepare the response packet */
reqid = pktp->pdu.std_pdu.request_id;
#if (INSTALL_ENVOY_SNMP_LOCK)
if (ENVOY_SNMP_GET_WRITE_LOCK(SNMP_ProxyLock)) {
BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0,
(BUG_OUT, "SNMP_Proxy_Response: proxy lock broken", 0));
pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst, 1,
pktp->async_cookie);
return 1;
}
#endif
for(pcbp = &pcb_root; *pcbp; pcbp = &(*pcbp)->next)
if ((*pcbp)->indx == reqid) {
pcb = *pcbp;
*pcbp = pcb->next;
break;
}
ENVOY_SNMP_RELEASE_WRITE_LOCK(SNMP_ProxyLock);
/* if we didn't find any state drop the packet */
if (pcb == 0) {
pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst, 1,
pktp->async_cookie);
return 1;
}
/* Indicate that we are done with the addressing information
from the respone packet */
pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst, 0, pktp->async_cookie);
/* restore the state */
pktp->pdu.std_pdu.request_id = pcb->reqid;
MEMCPY(&pktp->pkt_dst, &pcb->loc_addr, sizeof(SNMPADDR_T));
MEMCPY(&pktp->pkt_src, &pcb->for_addr, sizeof(SNMPADDR_T));
pktp->io_complete = pcb->io_comp;
pktp->error_complete = pcb->err_comp;
pktp->async_cookie = pcb->async_cookie;
pktp->maxpkt = pcb->maxpkt;
pktp->pdu_type = pcb->pdu_type;
pktp->snmp_version = pcb->original_version;
/* Clean up the current community string and then
replace it with the saved community string */
EBufferClean(&pktp->community);
EBufferPreLoad(pcb->community.bflags, &pktp->community,
EBufferStart(&pcb->community),
EBufferUsed(&pcb->community));
EBufferInitialize(&pcb->community);
/* we are done with the pcb so clean it up */
Clean_PCB(pcb);
/* If the current packet doesn't have it we need to get the read lock */
#if (INSTALL_ENVOY_SNMP_LOCK)
if (pktp->lockflags == LOCK_NOLOCK) {
if (ENVOY_SNMP_GET_READ_LOCK(SNMP_CoarseLock)) {
BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0,
(BUG_OUT,
"SNMP_Proxy_Response: coarse lock broken",
0));
pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst,
1, pktp->async_cookie);
return 1;
}
pktp->lockflags = LOCK_READ;
pktp->coarse_lock = &SNMP_CoarseLock;
}
#endif
/* determine if the packet is small enough to be sent out */
pktsize = SNMP_Bufsize_For_Packet(pktp);
if (pktsize > pktp->maxpkt) {
switch (pktp->pdu_type) {
case GET_REQUEST_PDU:
case GET_NEXT_REQUEST_PDU:
/* set up an alternate response, strip the vbl and
tag it as too_big */
Clean_vb_list(&pktp->pdu.std_pdu.std_vbl);
pktp->pdu.std_pdu.std_vbl.vblist = 0;
pktp->pdu.std_pdu.std_vbl.vbl_count = 0;
pktp->pdu.std_pdu.error_status = TOO_BIG;
pktp->pdu.std_pdu.error_index = 0;
break;
#if (INSTALL_ENVOY_SNMP_VERSION_2)
case GET_BULK_REQUEST_PDU:
/* if we have a BULK request we may need to remove vbs to
fit in to the maximum packet size */
{
int indx;
VB_T *vbp;
for (indx = pktp->pdu.std_pdu.std_vbl.vbl_count,
vbp = pktp->pdu.std_pdu.std_vbl.vblist + indx - 1;
indx;
indx--, vbp--) {
Clean_vb(vbp);
/* Recalculate the pktsize, 2 is for the tag and length
fields, the length field may be greater than 1 but
that is ok, the only thing that will happen is we
may put less than the maximum in a buffer */
pktsize -= 2 + vbp->vb_seq_size;
if (pktsize < pktp->maxpkt) {
pktp->pdu.std_pdu.std_vbl.vbl_count = indx - 1;
break;
}
}
}
break;
#endif /* #if (INSTALL_ENVOY_SNMP_VERSION_2) */
}
}
ENVOY_Send_SNMP_Packet(pktp);
return 0;
}
/****************************************************************************
NAME: SNMP_Proxy_Traps_And_Reports
PURPOSE: Provide proxy handling for traps and reports
Figure out if we have the information for a proxy
event, if so ship the message onward if not tag
the appropriate error. In any case indicate that
we are finished with the packet and free it.
PARAMETERS:
SNMP_PKT_T * Packet we're working on
RETURNS: void
****************************************************************************/
void
SNMP_Proxy_Traps_And_Reports(SNMP_PKT_T *pktp)
{
/* If we don't have a translation routine we bail out */
if (pktp->proxy_routine == 0) {
pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst,
1, pktp->async_cookie);
return;
}
/* If the current packet doesn't have it we need to get the read lock */
#if (INSTALL_ENVOY_SNMP_LOCK)
if (pktp->lockflags == LOCK_NOLOCK) {
if (ENVOY_SNMP_GET_READ_LOCK(SNMP_CoarseLock)) {
BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0,
(BUG_OUT,
"SNMP_Proxy_Traps_and_Reports: coarse lock broken",
0));
pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst,
1, pktp->async_cookie);
return;
}
pktp->lockflags = LOCK_READ;
pktp->coarse_lock = &SNMP_CoarseLock;
}
#endif
if ((((INT_32_T (*) __((SNMP_PKT_T *)))(pktp->proxy_routine))(pktp)) < 0)
pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst, 1,
pktp->async_cookie);
else
pktp->error_complete(&pktp->pkt_src, &pktp->pkt_dst, 0,
pktp->async_cookie);
return;
}
#endif /* INSTALL_ENVOY_SNMP_PROXY */