527 lines
15 KiB
C
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);
|
|
}
|
|
}
|
|
}
|
|
|