Files
2026-07-30 11:19:44 +05:30

527 lines
15 KiB
C

/*
* Copyright 2008 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.
*/
/* udp_mth.c - method routines for the udp group */
/*
modification history
--------------------
01h,20oct08,y_t fix for access udptable timeout
01g,26may08,y_t update for the ipnet
01f,02may07,mdk merge from spr-dev for spin45A
01e,03oct06,jbl fix padded instances in udpEndpointTable
01d,19sep06,jbl clear up build warnings and errors
01c,18sep06,jbl fix udpEndpointTable
01b,11sep06,jbl IPv6 switchability
01a,07sep06,jbl fix htonl() references
*/
#include "ip_mth.h"
#include "ip_mibhand.h"
#include "ip_mibleaf.h"
#include <wrn/wm/snmp/engine/asn1conf.h>
#include <wrn/wm/snmp/engine/asn1.h>
#include <wrn/wm/snmp/engine/buffer.h>
#include <wrn/wm/snmp/engine/mib.h>
#include <wrn/wm/snmp/engine/localio.h>
#include <wrn/wm/snmp/engine/snmpdefs.h>
#include <wrn/wm/snmp/engine/snmp.h>
#include <wrn/wm/snmp/engine/auxfuncs.h>
#include <ipnet_config.h>
#include <ipcom_mib2_api.h>
#include <ipnet_ctrl.h>
#include <ipcom_route.h>
#include <ipcom_clib.h>
/**************************************************************************
* Defines
**************************************************************************/
#define ipVersion_unknown 0
#define ipVersion_ipv4 1
#define ipVersion_ipv6 2
#define ipVersion_ipv4z 3
#define ipVersion_ipv6z 4
/**************************************************************************
* Local structures
**************************************************************************/
typedef struct
{
int tcount;
OIDC_T * tlist;
Ipcom_mib2_UdpEndpointEntry * dataPtr;
boolean_t getnext; /* FALSE = getexact */
} udpEndpointEntry_cookie_t;
typedef struct
{
int tcount;
OIDC_T * tlist;
Ipcom_mib2_IcmpMsgStatsEntry * dataPtr;
boolean_t getnext; /* FALSE = getexact */
} icmpMsgStatsEntry_cookie_t;
typedef struct
{
Ipcom_mib2_udp_group udpGroup;
} udp_data_t;
/*
* Method routines for the udpEndpointTable:
*
* udpEndpointLocalAddressType -- not-accessible
* The address type of udpEndpointLocalAddress. Only
* IPv4, IPv4z, IPv6, and IPv6z addresses are expected, or
* unknown(0) if datagrams for all local IP addresses are
* accepted.
*
* udpEndpointLocalAddress -- not-accessible
* The local IP address for this UDP endpoint.
*
* The value of this object can be represented in three
* possible ways, depending on the characteristics of the
* listening application:
*
* 1. For an application that is willing to accept both
* IPv4 and IPv6 datagrams, the value of this object
* must be ''h (a zero-length octet-string), with
* the value of the corresponding instance of the
* udpEndpointLocalAddressType object being unknown(0).
*
* 2. For an application that is willing to accept only IPv4
* or only IPv6 datagrams, the value of this object
* must be '0.0.0.0' or '::', respectively, while the
* corresponding instance of the
* udpEndpointLocalAddressType object represents the
* appropriate address type.
*
* 3. For an application that is listening for data
* destined only to a specific IP address, the value
* of this object is the specific IP address for which
* this node is receiving packets, with the
* corresponding instance of the
* udpEndpointLocalAddressType object representing the
* appropriate address type.
*
* As this object is used in the index for the
* udpEndpointTable, implementors of this table should be
* careful not to create entries that would result in OIDs
* with more than 128 subidentifiers; else the information
* cannot be accessed using SNMPv1, SNMPv2c, or SNMPv3.
*
* udpEndpointLocalPort -- not-accessible
* The local port number for this UDP endpoint.
*
* udpEndpointRemoteAddressType -- not-accessible
* The address type of udpEndpointRemoteAddress. Only
* IPv4, IPv4z, IPv6, and IPv6z addresses are expected, or
* unknown(0) if datagrams for all remote IP addresses are
* accepted. Also, note that some combinations of
* udpEndpointLocalAdressType and
* udpEndpointRemoteAddressType are not supported. In
* particular, if the value of this object is not
* unknown(0), it is expected to always refer to the
* same IP version as udpEndpointLocalAddressType.
*
* udpEndpointRemoteAddress -- not-accessible
* The remote IP address for this UDP endpoint. If
* datagrams from any remote system are to be accepted,
* this value is ''h (a zero-length octet-string).
* Otherwise, it has the type described by
* udpEndpointRemoteAddressType and is the address of the
* remote system from which datagrams are to be accepted
* (or to which all datagrams will be sent).
*
* As this object is used in the index for the
* udpEndpointTable, implementors of this table should be
* careful not to create entries that would result in OIDs
* with more than 128 subidentifiers; else the information
* cannot be accessed using SNMPv1, SNMPv2c, or SNMPv3.
*
* udpEndpointRemotePort -- not-accessible
* The remote port number for this UDP endpoint. If
* datagrams from any remote system are to be accepted,
* this value is zero.
*
* udpEndpointInstance -- not-accessible
* The instance of this tuple. This object is used to
* distinguish among multiple processes 'connected' to
* the same UDP endpoint. For example, on a system
* implementing the BSD sockets interface, this would be
* used to support the SO_REUSEADDR and SO_REUSEPORT
* socket options.
*
* udpEndpointProcess -- read-only
* The system's process ID for the process associated with
* this endpoint, or zero if there is no such process.
* This value is expected to be the same as
* HOST-RESOURCES-MIB::hrSWRunIndex or SYSAPPL-MIB::
* sysApplElmtRunIndex for some row in the appropriate
* tables.
*/
static int udpEndpointEntry_get_value
(
OIDC_T lastmatch,
SNMP_PKT_T *pktp,
VB_T *vbp,
Ipcom_mib2_UdpEndpointEntry *data)
{
switch (lastmatch) {
case LEAF_udpEndpointProcess:
getproc_got_uint32 (pktp, vbp, data->udpEndpointProcess, VT_GAUGE);
break;
default:
return GEN_ERR;
}
return NO_ERROR;
}
#define udpEndpointEntry_INSTANCE_LEN 47
static unsigned udpEndpointEntry_build_instance
(
Ipcom_mib2_UdpEndpointEntry *data,
OIDC_T *instance)
{
int i = 0;
int j = 0;
instance [0] = data->udpEndpointLocalAddressType;
switch (instance[0])
{
case ipVersion_unknown:
instance[1] = 0;
break;
case ipVersion_ipv4:
instance[1] = 4;
break;
case ipVersion_ipv4z:
instance[1] = 8;
break;
case ipVersion_ipv6:
instance[1] = 16;
break;
case ipVersion_ipv6z:
instance[1] = 20;
break;
default:
instance[1] = 0;
break;
}
for (i = 0; i < instance[1]; i++)
{
instance[2 + i] = data->udpEndpointLocalAddress[i];
}
j = instance[1] + 2;
instance[j] = data->udpEndpointLocalPort;
instance[j+1] = data->udpEndpointRemoteAddressType;
switch (instance[j+1])
{
case ipVersion_unknown:
instance[j+2] = 0;
break;
case ipVersion_ipv4:
instance[j+2] = 4;
break;
case ipVersion_ipv4z:
instance[j+2] = 8;
break;
case ipVersion_ipv6:
instance[j+2] = 16;
break;
case ipVersion_ipv6z:
instance[j+2] = 20;
break;
}
for (i = 0; i < instance[j+2]; i++)
{
instance[j+3+i] = data->udpEndpointRemoteAddress[i];
}
instance[j + 2 + instance[j + 2] + 1] = data->udpEndpointRemotePort;
instance[j + 2 + instance[j + 2] + 2] = data->udpEndpointInstance;
return (j + 2 + instance[j + 2] + 3);
}
static int
udpEndpointEntry_callback
(
Ipcom_mib2_UdpEndpointEntry *entry,
void *user)
{
udpEndpointEntry_cookie_t * cookie = (udpEndpointEntry_cookie_t *)user;
boolean_t stopIterating = FALSE;
boolean_t saveData = FALSE;
OIDC_T instance [udpEndpointEntry_INSTANCE_LEN];
unsigned instanceLen = 0;
int cmpval = 0;
instanceLen = udpEndpointEntry_build_instance (entry, instance);
cmpval = oidcmp2 (instanceLen, instance, cookie->tcount, cookie->tlist);
if (cookie->getnext)
{
if (cmpval > 0)
{
if (cookie->dataPtr == NULL)
saveData = TRUE;
else
{
OIDC_T prevInstance [udpEndpointEntry_INSTANCE_LEN];
unsigned prevInstanceLen = 0;
prevInstanceLen = udpEndpointEntry_build_instance (cookie->dataPtr,
prevInstance);
if (oidcmp2 (instanceLen, instance, prevInstanceLen, prevInstance) < 0)
saveData = TRUE;
}
}
}
else /* Get exact */
{
if (cmpval == 0)
{
saveData = TRUE;
stopIterating = TRUE;
}
}
if (saveData)
{
if (cookie->dataPtr == NULL)
cookie->dataPtr = SNMP_memory_alloc (sizeof (Ipcom_mib2_UdpEndpointEntry));
if (cookie->dataPtr != NULL)
memcpy (cookie->dataPtr, entry, sizeof (Ipcom_mib2_UdpEndpointEntry));
}
/* Return values defined are part of callback API. */
return (stopIterating? 1: 0);
}
static Ipcom_mib2_UdpEndpointEntry *
udpEndpointEntry_lookup
(
int tcount,
OIDC_T * tlist,
boolean_t getnext)
{
udpEndpointEntry_cookie_t cookie;
cookie.tcount = tcount;
cookie.tlist = tlist;
cookie.dataPtr = NULL;
cookie.getnext = getnext;
ipcom_mib2_iterate_udpEndpointTable (udpEndpointEntry_callback,
(void *)&cookie);
return (cookie.dataPtr);
}
void
udpEndpointEntry_get (OIDC_T lastmatch,
int tcount,
OIDC_T *tlist,
SNMP_PKT_T *pktp,
VB_T *vbp)
{
Ipcom_mib2_UdpEndpointEntry *data;
int error;
/* find all the varbinds that share the same getproc and instance */
group_by_getproc_and_instance (pktp, vbp, tcount, tlist);
if ((data = udpEndpointEntry_lookup (tcount, tlist, FALSE)) == NULL)
{
for ( ; vbp; vbp = vbp->vb_link)
getproc_nosuchins (pktp, vbp);
}
else
{
/* retrieve all the values from the same data structure */
for ( ; vbp; vbp = vbp->vb_link)
{
if ((error = udpEndpointEntry_get_value (vbp->vb_ml.ml_last_match, pktp, vbp, data)) != NO_ERROR)
getproc_error (pktp, vbp, error);
}
SNMP_memory_free (data);
}
}
void udpEndpointEntry_next
(
OIDC_T lastmatch,
int tcount,
OIDC_T *tlist,
SNMP_PKT_T *pktp,
VB_T *vbp
)
{
Ipcom_mib2_UdpEndpointEntry * data;
OIDC_T best_inst [udpEndpointEntry_INSTANCE_LEN];
int error;
unsigned best_inst_len;
/* find all the varbinds that share the same getproc and instance */
group_by_getproc_and_instance (pktp, vbp, tcount, tlist);
if ((data = udpEndpointEntry_lookup (tcount, tlist, TRUE)) != NULL)
{
best_inst_len = udpEndpointEntry_build_instance (data, best_inst);
/* we found a next so get the values and set the instance for all
* the varbinds for this row of this table. */
for ( ; vbp ; vbp = vbp->vb_link)
{
if ((error = udpEndpointEntry_get_value (vbp->vb_ml.ml_last_match, pktp, vbp, data)) == NO_ERROR)
nextproc_next_instance (pktp, vbp, best_inst_len, best_inst);
else
nextproc_error (pktp, vbp, error);
}
SNMP_memory_free (data);
}
else /* there's no more in this table */
{
for ( ; vbp ; vbp = vbp->vb_link )
nextproc_no_next (pktp, vbp);
}
}
/*
* Method routines for the udp variables:
*
* udpInDatagrams -- read-only
* The total number of UDP datagrams delivered to
* UDP users.
*
* udpNoPorts -- read-only
* The total number of received UDP datagrams for
* which there was no application at the destination
* port.
*
* udpInErrors -- read-only
* The number of received UDP datagrams that could
* not be delivered for reasons other than the lack
* of an application at the destination port.
*
* udpOutDatagrams -- read-only
* The total number of UDP datagrams sent from this
* entity.
*/
/* An internal routine to retrieve the values of the variables, used
* by the method routines udp_get and udp_next.
*/
static int udp_get_value
(
OIDC_T lastmatch,
SNMP_PKT_T *pktp,
VB_T *vbp,
udp_data_t *data
)
{
switch(lastmatch)
{
case LEAF_udpInDatagrams:
getproc_got_uint32(pktp, vbp, data->udpGroup.udpInDatagrams,
VT_COUNTER);
break;
case LEAF_udpNoPorts:
getproc_got_uint32(pktp, vbp, data->udpGroup.udpNoPorts, VT_COUNTER);
break;
case LEAF_udpInErrors:
getproc_got_uint32(pktp, vbp, data->udpGroup.udpInErrors, VT_COUNTER);
break;
case LEAF_udpOutDatagrams:
getproc_got_uint32(pktp, vbp, data->udpGroup.udpOutDatagrams,
VT_COUNTER);
break;
case LEAF_udpHCInDatagrams:
getproc_got_uint32(pktp, vbp, (UINT_32_T)data->udpGroup.udpHCInDatagrams,
VT_COUNTER64);
break;
case LEAF_udpHCOutDatagrams:
getproc_got_uint32(pktp, vbp, (UINT_32_T)data->udpGroup.udpHCOutDatagrams,
VT_COUNTER64);
break;
default:
return GEN_ERR;
}
return NO_ERROR;
}
static int
udp_lookup (udp_data_t * dataP)
{
int retVal = 0;
retVal |= ipcom_mib2_get_udp_group(&(dataP->udpGroup));
return retVal;
}
void udp_get
(
OIDC_T lastmatch,
int tcount,
OIDC_T *tlist,
SNMP_PKT_T *pktp,
VB_T *vbp
)
{
udp_data_t data;
int error;
/* find all the varbinds that share the same getproc and instance */
group_by_getproc_and_instance (pktp, vbp, tcount, tlist);
/* check that the instance is exactly .0 */
if (!((tcount == 1) && (*tlist == 0)))
{
for ( ; vbp; vbp = vbp->vb_link)
getproc_nosuchins(pktp, vbp);
}
else if (udp_lookup(&data) != 0)
{
for ( ; vbp; vbp = vbp->vb_link)
getproc_error(pktp, vbp, GEN_ERR);
}
else
{
/* retrieve all the values from the same data structure */
for ( ; vbp; vbp = vbp->vb_link)
{
if ((error = udp_get_value (vbp->vb_ml.ml_last_match, pktp, vbp, &data)) != NO_ERROR)
getproc_error(pktp, vbp, error);
}
}
}