/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include /************************************************************************** * 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); } } }