Sergey Pastor / 1

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mib2_impl.c Source File

mib2_impl.c

Go to the documentation of this file.
00001 /**
00002  * @file mib2_impl.c
00003  * @brief MIB-II module implementation
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneTCP Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Dependencies
00030 #include "core/net.h"
00031 #include "mibs/mib_common.h"
00032 #include "mibs/mib2_module.h"
00033 #include "mibs/mib2_impl.h"
00034 #include "crypto.h"
00035 #include "asn1.h"
00036 #include "oid.h"
00037 #include "debug.h"
00038 
00039 //Check TCP/IP stack configuration
00040 #if (MIB2_SUPPORT == ENABLED)
00041 
00042 
00043 /**
00044  * @brief MIB-II module initialization
00045  * @return Error code
00046  **/
00047 
00048 error_t mib2Init(void)
00049 {
00050    uint_t i;
00051    Mib2SysGroup *sysGroup;
00052    Mib2IfGroup *ifGroup;
00053 #if (IPV4_SUPPORT == ENABLED)
00054    Mib2IpGroup *ipGroup;
00055 #endif
00056 #if (TCP_SUPPORT == ENABLED)
00057    Mib2TcpGroup *tcpGroup;
00058 #endif
00059 
00060    //Debug message
00061    TRACE_INFO("Initializing standard MIB-II base...\r\n");
00062 
00063    //Clear MIB-II base
00064    memset(&mib2Base, 0, sizeof(mib2Base));
00065 
00066    //Point to the system group
00067    sysGroup = &mib2Base.sysGroup;
00068 
00069 #if (MIB2_SYS_DESCR_SIZE > 0)
00070    //sysDescr object
00071    strcpy(sysGroup->sysDescr, "Description");
00072    sysGroup->sysDescrLen = strlen(sysGroup->sysDescr);
00073 #endif
00074 
00075 #if (MIB2_SYS_OBJECT_ID_SIZE > 0)
00076    //sysObjectID object
00077    sysGroup->sysObjectID[0] = 0;
00078    sysGroup->sysObjectIDLen = 1;
00079 #endif
00080 
00081 #if (MIB2_SYS_CONTACT_SIZE > 0)
00082    //sysContact object
00083    strcpy(sysGroup->sysContact, "Contact");
00084    sysGroup->sysContactLen = strlen(sysGroup->sysContact);
00085 #endif
00086 
00087 #if (MIB2_SYS_NAME_SIZE > 0)
00088    //sysName object
00089    strcpy(sysGroup->sysName, "Name");
00090    sysGroup->sysNameLen = strlen(sysGroup->sysName);
00091 #endif
00092 
00093 #if (MIB2_SYS_LOCATION_SIZE > 0)
00094    //sysLocation object
00095    strcpy(sysGroup->sysLocation, "Location");
00096    sysGroup->sysLocationLen = strlen(sysGroup->sysLocation);
00097 #endif
00098 
00099    //sysServices object
00100    sysGroup->sysServices = MIB2_SYS_SERVICE_INTERNET;
00101 
00102    //Point to the interfaces group
00103    ifGroup = &mib2Base.ifGroup;
00104 
00105    //Interfaces table entry
00106    for(i = 0; i < NET_INTERFACE_COUNT; i++)
00107    {
00108       //ifSpecific object
00109       ifGroup->ifTable[i].ifSpecific[0] = 0;
00110       ifGroup->ifTable[i].ifSpecificLen = 1;
00111    }
00112 
00113 #if (IPV4_SUPPORT == ENABLED)
00114    //Point to the IP group
00115    ipGroup = &mib2Base.ipGroup;
00116 
00117    //ipForwarding object
00118    ipGroup->ipForwarding = MIB2_IP_FORWARDING_DISABLED;
00119    //ipDefaultTTL object
00120    ipGroup->ipDefaultTTL = IPV4_DEFAULT_TTL;
00121    //ipReasmTimeout object
00122    ipGroup->ipReasmTimeout = IPV4_FRAG_TIME_TO_LIVE / 1000;
00123 #endif
00124 
00125 #if (TCP_SUPPORT == ENABLED)
00126    //Point to the TCP group
00127    tcpGroup = &mib2Base.tcpGroup;
00128 
00129    //tcpRtoAlgorithm object
00130    tcpGroup->tcpRtoAlgorithm = MIB2_TCP_RTO_ALGORITHM_VANJ;
00131    //tcpRtoMin object
00132    tcpGroup->tcpRtoMin = TCP_MIN_RTO;
00133    //tcpRtoMax object
00134    tcpGroup->tcpRtoMax = TCP_MAX_RTO;
00135    //tcpMaxConn object
00136    tcpGroup->tcpMaxConn = SOCKET_MAX_COUNT;
00137 #endif
00138 
00139    //Successful processing
00140    return NO_ERROR;
00141 }
00142 
00143 
00144 /**
00145  * @brief Lock MIB-II base
00146  **/
00147 
00148 void mib2Lock(void)
00149 {
00150    //Get exclusive access
00151    osAcquireMutex(&netMutex);
00152 }
00153 
00154 
00155 /**
00156  * @brief Unlock MIB-II base
00157  **/
00158 
00159 void mib2Unlock(void)
00160 {
00161    //Release exclusive access
00162    osReleaseMutex(&netMutex);
00163 }
00164 
00165 
00166 /**
00167  * @brief Get sysUpTime object value
00168  * @param[in] object Pointer to the MIB object descriptor
00169  * @param[in] oid Object identifier (object name and instance identifier)
00170  * @param[in] oidLen Length of the OID, in bytes
00171  * @param[out] value Object value
00172  * @param[in,out] valueLen Length of the object value, in bytes
00173  * @return Error code
00174  **/
00175 
00176 error_t mib2GetSysUpTime(const MibObject *object, const uint8_t *oid,
00177    size_t oidLen, MibVariant *value, size_t *valueLen)
00178 {
00179    //Get object value
00180    value->timeTicks = osGetSystemTime() / 10;
00181    //Successful processing
00182    return NO_ERROR;
00183 }
00184 
00185 
00186 /**
00187  * @brief Get ifEntry object value
00188  * @param[in] object Pointer to the MIB object descriptor
00189  * @param[in] oid Object identifier (object name and instance identifier)
00190  * @param[in] oidLen Length of the OID, in bytes
00191  * @param[out] value Object value
00192  * @param[in,out] valueLen Length of the object value, in bytes
00193  * @return Error code
00194  **/
00195 
00196 error_t mib2GetIfEntry(const MibObject *object, const uint8_t *oid,
00197    size_t oidLen, MibVariant *value, size_t *valueLen)
00198 {
00199    error_t error;
00200    size_t n;
00201    uint_t index;
00202    Mib2IfEntry *entry;
00203 
00204    //Point to the instance identifier
00205    n = object->oidLen;
00206 
00207    //The ifIndex is used as instance identifier
00208    error = mibDecodeIndex(oid, oidLen, &n, &index);
00209    //Invalid instance identifier?
00210    if(error)
00211       return error;
00212 
00213    //Sanity check
00214    if(n != oidLen)
00215       return ERROR_INSTANCE_NOT_FOUND;
00216 
00217    //Check index range
00218    if(index < 1 || index > NET_INTERFACE_COUNT)
00219       return ERROR_INSTANCE_NOT_FOUND;
00220 
00221    //Point to the interface table entry
00222    entry = &mib2Base.ifGroup.ifTable[index - 1];
00223 
00224    //ifIndex object?
00225    if(!strcmp(object->name, "ifIndex"))
00226    {
00227       //Get object value
00228       value->integer = entry->ifIndex;
00229    }
00230    //ifDescr object?
00231    else if(!strcmp(object->name, "ifDescr"))
00232    {
00233       //Make sure the buffer is large enough to hold the entire object
00234       if(*valueLen >= entry->ifDescrLen)
00235       {
00236          //Copy object value
00237          memcpy(value->octetString, entry->ifDescr, entry->ifDescrLen);
00238          //Return object length
00239          *valueLen = entry->ifDescrLen;
00240       }
00241       else
00242       {
00243          //Report an error
00244          error = ERROR_BUFFER_OVERFLOW;
00245       }
00246    }
00247    //ifType object?
00248    else if(!strcmp(object->name, "ifType"))
00249    {
00250       //Get object value
00251       value->integer = entry->ifType;
00252    }
00253    //ifMtu object?
00254    else if(!strcmp(object->name, "ifMtu"))
00255    {
00256       //Get object value
00257       value->integer = entry->ifMtu;
00258    }
00259    //ifSpeed object?
00260    else if(!strcmp(object->name, "ifSpeed"))
00261    {
00262       //Get object value
00263       value->gauge32 = entry->ifSpeed;
00264    }
00265    //ifPhysAddress object?
00266    else if(!strcmp(object->name, "ifPhysAddress"))
00267    {
00268       //Make sure the buffer is large enough to hold the entire object
00269       if(*valueLen >= entry->ifPhysAddressLen)
00270       {
00271          //Copy object value
00272          memcpy(value->octetString, entry->ifPhysAddress, entry->ifPhysAddressLen);
00273          //Return object length
00274          *valueLen = entry->ifPhysAddressLen;
00275       }
00276       else
00277       {
00278          //Report an error
00279          error = ERROR_BUFFER_OVERFLOW;
00280       }
00281    }
00282    //ifAdminStatus object?
00283    else if(!strcmp(object->name, "ifAdminStatus"))
00284    {
00285       //Get object value
00286       value->integer = entry->ifAdminStatus;
00287    }
00288    //ifOperStatus object?
00289    else if(!strcmp(object->name, "ifOperStatus"))
00290    {
00291       //Get object value
00292       value->integer = entry->ifOperStatus;
00293    }
00294    //ifLastChange object?
00295    else if(!strcmp(object->name, "ifLastChange"))
00296    {
00297       //Get object value
00298       value->timeTicks = entry->ifLastChange;
00299    }
00300    //ifInOctets object?
00301    else if(!strcmp(object->name, "ifInOctets"))
00302    {
00303       //Get object value
00304       value->counter32 = entry->ifInOctets;
00305    }
00306    //ifInUcastPkts object?
00307    else if(!strcmp(object->name, "ifInUcastPkts"))
00308    {
00309       //Get object value
00310       value->counter32 = entry->ifInUcastPkts;
00311    }
00312    //ifInNUcastPkts object?
00313    else if(!strcmp(object->name, "ifInNUcastPkts"))
00314    {
00315       //Get object value
00316       value->counter32 = entry->ifInNUcastPkts;
00317    }
00318    //ifInDiscards object?
00319    else if(!strcmp(object->name, "ifInDiscards"))
00320    {
00321       //Get object value
00322       value->counter32 = entry->ifInDiscards;
00323    }
00324    //ifInErrors object?
00325    else if(!strcmp(object->name, "ifInErrors"))
00326    {
00327       //Get object value
00328       value->counter32 = entry->ifInErrors;
00329    }
00330    //ifInUnknownProtos object?
00331    else if(!strcmp(object->name, "ifInUnknownProtos"))
00332    {
00333       //Get object value
00334       value->counter32 = entry->ifInUnknownProtos;
00335    }
00336    //ifOutOctets object?
00337    else if(!strcmp(object->name, "ifOutOctets"))
00338    {
00339       //Get object value
00340       value->counter32 = entry->ifOutOctets;
00341    }
00342    //ifOutUcastPkts object?
00343    else if(!strcmp(object->name, "ifOutUcastPkts"))
00344    {
00345       //Get object value
00346       value->counter32 = entry->ifOutUcastPkts;
00347    }
00348    //ifOutNUcastPkts object?
00349    else if(!strcmp(object->name, "ifOutNUcastPkts"))
00350    {
00351       //Get object value
00352       value->counter32 = entry->ifOutNUcastPkts;
00353    }
00354    //ifOutDiscards object?
00355    else if(!strcmp(object->name, "ifOutDiscards"))
00356    {
00357       //Get object value
00358       value->counter32 = entry->ifOutDiscards;
00359    }
00360    //ifOutErrors object?
00361    else if(!strcmp(object->name, "ifOutErrors"))
00362    {
00363       //Get object value
00364       value->counter32 = entry->ifOutErrors;
00365    }
00366    //ifOutQLen object?
00367    else if(!strcmp(object->name, "ifOutQLen"))
00368    {
00369       //Get object value
00370       value->gauge32 = entry->ifOutQLen;
00371    }
00372    //ifSpecific object?
00373    else if(!strcmp(object->name, "ifSpecific"))
00374    {
00375       //Make sure the buffer is large enough to hold the entire object
00376       if(*valueLen >= entry->ifSpecificLen)
00377       {
00378          //Copy object value
00379          memcpy(value->oid, entry->ifSpecific, entry->ifSpecificLen);
00380          //Return object length
00381          *valueLen = entry->ifSpecificLen;
00382       }
00383       else
00384       {
00385          //Report an error
00386          error = ERROR_BUFFER_OVERFLOW;
00387       }
00388    }
00389    //Unknown object?
00390    else
00391    {
00392       //The specified object does not exist
00393       error = ERROR_OBJECT_NOT_FOUND;
00394    }
00395 
00396    //Return status code
00397    return error;
00398 }
00399 
00400 
00401 /**
00402  * @brief Get next ifEntry object
00403  * @param[in] object Pointer to the MIB object descriptor
00404  * @param[in] oid Object identifier
00405  * @param[in] oidLen Length of the OID, in bytes
00406  * @param[out] nextOid OID of the next object in the MIB
00407  * @param[out] nextOidLen Length of the next object identifier, in bytes
00408  * @return Error code
00409  **/
00410 
00411 error_t mib2GetNextIfEntry(const MibObject *object, const uint8_t *oid,
00412    size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
00413 {
00414    error_t error;
00415    size_t n;
00416    uint_t index;
00417 
00418    //Make sure the buffer is large enough to hold the OID prefix
00419    if(*nextOidLen < object->oidLen)
00420       return ERROR_BUFFER_OVERFLOW;
00421 
00422    //Copy OID prefix
00423    memcpy(nextOid, object->oid, object->oidLen);
00424 
00425    //Loop through network interfaces
00426    for(index = 1; index <= NET_INTERFACE_COUNT; index++)
00427    {
00428       //Append the instance identifier to the OID prefix
00429       n = object->oidLen;
00430 
00431       //The ifIndex is used as instance identifier
00432       error = mibEncodeIndex(nextOid, *nextOidLen, &n, index);
00433       //Any error to report?
00434       if(error)
00435          return error;
00436 
00437       //Check whether the resulting object identifier lexicographically
00438       //follows the specified OID
00439       if(oidComp(nextOid, n, oid, oidLen) > 0)
00440       {
00441          //Save the length of the resulting object identifier
00442          *nextOidLen = n;
00443          //Next object found
00444          return NO_ERROR;
00445       }
00446    }
00447 
00448    //The specified OID does not lexicographically precede the name
00449    //of some object
00450    return ERROR_OBJECT_NOT_FOUND;
00451 }
00452 
00453 
00454 #if (IPV4_SUPPORT == ENABLED)
00455 
00456 /**
00457  * @brief Get ipAddrEntry object value
00458  * @param[in] object Pointer to the MIB object descriptor
00459  * @param[in] oid Object identifier (object name and instance identifier)
00460  * @param[in] oidLen Length of the OID, in bytes
00461  * @param[out] value Object value
00462  * @param[in,out] valueLen Length of the object value, in bytes
00463  * @return Error code
00464  **/
00465 
00466 error_t mib2GetIpAddrEntry(const MibObject *object, const uint8_t *oid,
00467    size_t oidLen, MibVariant *value, size_t *valueLen)
00468 {
00469    error_t error;
00470    uint_t i;
00471    size_t n;
00472    Ipv4Addr ipAddr;
00473    NetInterface *interface;
00474 
00475    //Point to the instance identifier
00476    n = object->oidLen;
00477 
00478    //The ipAdEntAddr is used as instance identifier
00479    error = mibDecodeIpv4Addr(oid, oidLen, &n, &ipAddr);
00480    //Invalid instance identifier?
00481    if(error)
00482       return error;
00483 
00484    //Sanity check
00485    if(n != oidLen)
00486       return ERROR_INSTANCE_NOT_FOUND;
00487 
00488    //Loop through network interfaces
00489    for(i = 0; i < NET_INTERFACE_COUNT; i++)
00490    {
00491       //Point to the current interface
00492       interface = &netInterface[i];
00493 
00494       //Check address state
00495       if(interface->ipv4Context.addrState == IPV4_ADDR_STATE_VALID)
00496       {
00497          //Compare the current address against the IP address used as
00498          //instance identifier
00499          if(interface->ipv4Context.addr == ipAddr)
00500             break;
00501       }
00502    }
00503 
00504    //IP address not assigned to any interface?
00505    if(i >= NET_INTERFACE_COUNT)
00506       return ERROR_INSTANCE_NOT_FOUND;
00507 
00508    //ipAdEntAddr object?
00509    if(!strcmp(object->name, "ipAdEntAddr"))
00510    {
00511       //Get object value
00512       ipv4CopyAddr(value->ipAddr, &interface->ipv4Context.addr);
00513    }
00514    //ipAdEntIfIndex object?
00515    else if(!strcmp(object->name, "ipAdEntIfIndex"))
00516    {
00517       //Get object value
00518       value->integer = interface->id + 1;
00519    }
00520    //ipAdEntNetMask object?
00521    else if(!strcmp(object->name, "ipAdEntNetMask"))
00522    {
00523       //Get object value
00524       ipv4CopyAddr(value->ipAddr, &interface->ipv4Context.subnetMask);
00525    }
00526    //ipAdEntBcastAddr object?
00527    else if(!strcmp(object->name, "ipAdEntBcastAddr"))
00528    {
00529       //Get object value
00530       value->integer = 1;
00531    }
00532    //ipAdEntReasmMaxSize object?
00533    else if(!strcmp(object->name, "ipAdEntReasmMaxSize"))
00534    {
00535       //Get object value
00536       value->integer = IPV4_MAX_FRAG_DATAGRAM_SIZE;
00537    }
00538    //Unknown object?
00539    else
00540    {
00541       //The specified object does not exist
00542       error = ERROR_OBJECT_NOT_FOUND;
00543    }
00544 
00545    //Return status code
00546    return error;
00547 }
00548 
00549 
00550 /**
00551  * @brief Get next ipAddrEntry object
00552  * @param[in] object Pointer to the MIB object descriptor
00553  * @param[in] oid Object identifier
00554  * @param[in] oidLen Length of the OID, in bytes
00555  * @param[out] nextOid OID of the next object in the MIB
00556  * @param[out] nextOidLen Length of the next object identifier, in bytes
00557  * @return Error code
00558  **/
00559 
00560 error_t mib2GetNextIpAddrEntry(const MibObject *object, const uint8_t *oid,
00561    size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
00562 {
00563    error_t error;
00564    uint_t i;
00565    size_t n;
00566    Ipv4Addr ipAddr;
00567    NetInterface *interface;
00568 
00569    //Initialize IP address
00570    ipAddr = IPV4_UNSPECIFIED_ADDR;
00571 
00572    //Make sure the buffer is large enough to hold the OID prefix
00573    if(*nextOidLen < object->oidLen)
00574       return ERROR_BUFFER_OVERFLOW;
00575 
00576    //Copy OID prefix
00577    memcpy(nextOid, object->oid, object->oidLen);
00578 
00579    //Loop through network interfaces
00580    for(i = 0; i < NET_INTERFACE_COUNT; i++)
00581    {
00582       //Point to the current interface
00583       interface = &netInterface[i];
00584 
00585       //Check address state
00586       if(interface->ipv4Context.addrState == IPV4_ADDR_STATE_VALID)
00587       {
00588          //Append the instance identifier to the OID prefix
00589          n = object->oidLen;
00590 
00591          //The ipAdEntAddr is used as instance identifier
00592          error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, interface->ipv4Context.addr);
00593          //Any error to report?
00594          if(error)
00595             return error;
00596 
00597          //Check whether the resulting object identifier lexicographically
00598          //follows the specified OID
00599          if(oidComp(nextOid, n, oid, oidLen) > 0)
00600          {
00601             //Save the closest object identifier that follows the specified
00602             //OID in lexicographic order
00603             if(ipAddr == IPV4_UNSPECIFIED_ADDR)
00604             {
00605                ipAddr = interface->ipv4Context.addr;
00606             }
00607             else if(ntohl(interface->ipv4Context.addr) < ntohl(ipAddr))
00608             {
00609                ipAddr = interface->ipv4Context.addr;
00610             }
00611          }
00612       }
00613    }
00614 
00615    //The specified OID does not lexicographically precede the name
00616    //of some object?
00617    if(ipAddr == IPV4_UNSPECIFIED_ADDR)
00618       return ERROR_OBJECT_NOT_FOUND;
00619 
00620    //Append the instance identifier to the OID prefix
00621    n = object->oidLen;
00622 
00623    //The ipAdEntAddr is used as instance identifier
00624    error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, interface->ipv4Context.addr);
00625    //Any error to report?
00626    if(error)
00627       return error;
00628 
00629    //Save the length of the resulting object identifier
00630    *nextOidLen = n;
00631    //Next object found
00632    return NO_ERROR;
00633 }
00634 
00635 
00636 /**
00637  * @brief Set ipNetToMediaEntry object value
00638  * @param[in] object Pointer to the MIB object descriptor
00639  * @param[in] oid Object identifier (object name and instance identifier)
00640  * @param[in] oidLen Length of the OID, in bytes
00641  * @param[in] value Object value
00642  * @param[in] valueLen Length of the object value, in bytes
00643  * @return Error code
00644  **/
00645 
00646 error_t mib2SetIpNetToMediaEntry(const MibObject *object, const uint8_t *oid,
00647    size_t oidLen, const MibVariant *value, size_t valueLen)
00648 {
00649    //Not implemented
00650    return ERROR_WRITE_FAILED;
00651 }
00652 
00653 
00654 /**
00655  * @brief Get ipNetToMediaEntry object value
00656  * @param[in] object Pointer to the MIB object descriptor
00657  * @param[in] oid Object identifier (object name and instance identifier)
00658  * @param[in] oidLen Length of the OID, in bytes
00659  * @param[out] value Object value
00660  * @param[in,out] valueLen Length of the object value, in bytes
00661  * @return Error code
00662  **/
00663 
00664 error_t mib2GetIpNetToMediaEntry(const MibObject *object, const uint8_t *oid,
00665    size_t oidLen, MibVariant *value, size_t *valueLen)
00666 {
00667    error_t error;
00668    size_t n;
00669    uint_t index;
00670    Ipv4Addr ipAddr;
00671    NetInterface *interface;
00672    ArpCacheEntry *entry;
00673 
00674    //Point to the instance identifier
00675    n = object->oidLen;
00676 
00677    //The ipNetToMediaIfIndex is used as 1st instance identifier
00678    error = mibDecodeIndex(oid, oidLen, &n, &index);
00679    //Invalid instance identifier?
00680    if(error)
00681       return error;
00682 
00683    //The ipNetToMediaNetAddress is used as 2nd instance identifier
00684    error = mibDecodeIpv4Addr(oid, oidLen, &n, &ipAddr);
00685    //Invalid instance identifier?
00686    if(error)
00687       return error;
00688 
00689    //Sanity check
00690    if(n != oidLen)
00691       return ERROR_INSTANCE_NOT_FOUND;
00692 
00693    //Check index range
00694    if(index < 1 || index > NET_INTERFACE_COUNT)
00695       return ERROR_INSTANCE_NOT_FOUND;
00696 
00697    //Point to the network interface
00698    interface = &netInterface[index - 1];
00699 
00700    //Search the ARP cache for the specified IP address
00701    entry = arpFindEntry(interface, ipAddr);
00702 
00703    //No matching entry found?
00704    if(entry == NULL)
00705       return ERROR_INSTANCE_NOT_FOUND;
00706 
00707    //ipNetToMediaIfIndex object?
00708    if(!strcmp(object->name, "ipNetToMediaIfIndex"))
00709    {
00710       //Get object value
00711       value->integer = index;
00712    }
00713    //ipNetToMediaPhysAddress object?
00714    else if(!strcmp(object->name, "ipNetToMediaPhysAddress"))
00715    {
00716       //Make sure the buffer is large enough to hold the entire object
00717       if(*valueLen >= MIB2_PHYS_ADDRESS_SIZE)
00718       {
00719          //Copy object value
00720          macCopyAddr(value->octetString, &entry->macAddr);
00721          //Return object length
00722          *valueLen = MIB2_PHYS_ADDRESS_SIZE;
00723       }
00724       else
00725       {
00726          //Report an error
00727          error = ERROR_BUFFER_OVERFLOW;
00728       }
00729    }
00730    //ipNetToMediaNetAddress object?
00731    else if(!strcmp(object->name, "ipNetToMediaNetAddress"))
00732    {
00733       //Get object value
00734       ipv4CopyAddr(value->ipAddr, &entry->ipAddr);
00735    }
00736    //ipNetToMediaType object?
00737    else if(!strcmp(object->name, "ipNetToMediaType"))
00738    {
00739       //Get object value
00740       value->integer = MIB2_IP_NET_TO_MEDIA_TYPE_DYNAMIC;
00741    }
00742    //Unknown object?
00743    else
00744    {
00745       //The specified object does not exist
00746       error = ERROR_OBJECT_NOT_FOUND;
00747    }
00748 
00749    //Return status code
00750    return error;
00751 }
00752 
00753 
00754 /**
00755  * @brief Get next ipNetToMediaEntry object
00756  * @param[in] object Pointer to the MIB object descriptor
00757  * @param[in] oid Object identifier
00758  * @param[in] oidLen Length of the OID, in bytes
00759  * @param[out] nextOid OID of the next object in the MIB
00760  * @param[out] nextOidLen Length of the next object identifier, in bytes
00761  * @return Error code
00762  **/
00763 
00764 error_t mib2GetNextIpNetToMediaEntry(const MibObject *object, const uint8_t *oid,
00765    size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
00766 {
00767    error_t error;
00768    uint_t i;
00769    uint_t j;
00770    size_t n;
00771    uint32_t index;
00772    bool_t acceptable;
00773    Ipv4Addr ipAddr;
00774    NetInterface *interface;
00775    ArpCacheEntry *entry;
00776 
00777    //Initialize variables
00778    index = 0;
00779    ipAddr = IPV4_UNSPECIFIED_ADDR;
00780 
00781    //Make sure the buffer is large enough to hold the OID prefix
00782    if(*nextOidLen < object->oidLen)
00783       return ERROR_BUFFER_OVERFLOW;
00784 
00785    //Copy OID prefix
00786    memcpy(nextOid, object->oid, object->oidLen);
00787 
00788    //Loop through network interfaces
00789    for(i = 1; i <= NET_INTERFACE_COUNT; i++)
00790    {
00791       //Point to the current interface
00792       interface = &netInterface[i - 1];
00793 
00794       //Loop through ARP cache entries
00795       for(j = 0; j < ARP_CACHE_SIZE; j++)
00796       {
00797          //Point to the current entry
00798          entry = &interface->arpCache[j];
00799 
00800          //Valid entry?
00801          if(entry->state != ARP_STATE_NONE)
00802          {
00803             //Append the instance identifier to the OID prefix
00804             n = object->oidLen;
00805 
00806             //The ipNetToMediaIfIndex is used as 1st instance identifier
00807             error = mibEncodeIndex(nextOid, *nextOidLen, &n, i);
00808             //Any error to report?
00809             if(error)
00810                return error;
00811 
00812             //The ipNetToMediaNetAddress is used as 2nd instance identifier
00813             error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, entry->ipAddr);
00814             //Any error to report?
00815             if(error)
00816                return error;
00817 
00818             //Check whether the resulting object identifier lexicographically
00819             //follows the specified OID
00820             if(oidComp(nextOid, n, oid, oidLen) > 0)
00821             {
00822                //Perform lexicographic comparison
00823                if(index == 0)
00824                   acceptable = TRUE;
00825                else if(i < index)
00826                   acceptable = TRUE;
00827                else if(i > index)
00828                   acceptable = FALSE;
00829                else if(ntohl(entry->ipAddr) < ntohl(ipAddr))
00830                   acceptable = TRUE;
00831                else
00832                   acceptable = FALSE;
00833 
00834                //Save the closest object identifier that follows the specified
00835                //OID in lexicographic order
00836                if(acceptable)
00837                {
00838                   index = i;
00839                   ipAddr = entry->ipAddr;
00840                }
00841             }
00842          }
00843       }
00844    }
00845 
00846    //The specified OID does not lexicographically precede the name
00847    //of some object?
00848    if(index == 0)
00849       return ERROR_OBJECT_NOT_FOUND;
00850 
00851    //Append the instance identifier to the OID prefix
00852    n = object->oidLen;
00853 
00854    //The ipNetToMediaIfIndex is used as 1st instance identifier
00855    error = mibEncodeIndex(nextOid, *nextOidLen, &n, index);
00856    //Any error to report?
00857    if(error)
00858       return error;
00859 
00860    //The ipNetToMediaNetAddress is used as 2nd instance identifier
00861    error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, ipAddr);
00862    //Any error to report?
00863    if(error)
00864       return error;
00865 
00866    //Save the length of the resulting object identifier
00867    *nextOidLen = n;
00868    //Next object found
00869    return NO_ERROR;
00870 }
00871 
00872 
00873 /**
00874  * @brief Set tcpConnEntry object value
00875  * @param[in] object Pointer to the MIB object descriptor
00876  * @param[in] oid Object identifier (object name and instance identifier)
00877  * @param[in] oidLen Length of the OID, in bytes
00878  * @param[out] value Object value
00879  * @param[in] valueLen Length of the object value, in bytes
00880  * @return Error code
00881  **/
00882 
00883 error_t mib2SetTcpConnEntry(const MibObject *object, const uint8_t *oid,
00884    size_t oidLen, const MibVariant *value, size_t valueLen)
00885 {
00886    //Not implemented
00887    return ERROR_WRITE_FAILED;
00888 }
00889 
00890 
00891 /**
00892  * @brief Get tcpConnEntry object value
00893  * @param[in] object Pointer to the MIB object descriptor
00894  * @param[in] oid Object identifier (object name and instance identifier)
00895  * @param[in] oidLen Length of the OID, in bytes
00896  * @param[out] value Object value
00897  * @param[in,out] valueLen Length of the object value, in bytes
00898  * @return Error code
00899  **/
00900 
00901 error_t mib2GetTcpConnEntry(const MibObject *object, const uint8_t *oid,
00902    size_t oidLen, MibVariant *value, size_t *valueLen)
00903 {
00904    error_t error;
00905    uint_t i;
00906    size_t n;
00907    Ipv4Addr localIpAddr;
00908    uint16_t localPort;
00909    Ipv4Addr remoteIpAddr;
00910    uint16_t remotePort;
00911    Socket *socket;
00912 
00913    //Point to the instance identifier
00914    n = object->oidLen;
00915 
00916    //The tcpConnLocalAddress is used as 1st instance identifier
00917    error = mibDecodeIpv4Addr(oid, oidLen, &n, &localIpAddr);
00918    //Invalid instance identifier?
00919    if(error)
00920       return error;
00921 
00922    //The tcpConnLocalPort is used as 2nd instance identifier
00923    error = mibDecodePort(oid, oidLen, &n, &localPort);
00924    //Invalid instance identifier?
00925    if(error)
00926       return error;
00927 
00928    //The tcpConnRemAddress is used as 3rd instance identifier
00929    error = mibDecodeIpv4Addr(oid, oidLen, &n, &remoteIpAddr);
00930    //Invalid instance identifier?
00931    if(error)
00932       return error;
00933 
00934    //The tcpConnRemPort is used as 4th instance identifier
00935    error = mibDecodePort(oid, oidLen, &n, &remotePort);
00936    //Invalid instance identifier?
00937    if(error)
00938       return error;
00939 
00940    //Sanity check
00941    if(n != oidLen)
00942       return ERROR_INSTANCE_NOT_FOUND;
00943 
00944    //Loop through socket descriptors
00945    for(i = 0; i < SOCKET_MAX_COUNT; i++)
00946    {
00947       //Point to current socket
00948       socket = &socketTable[i];
00949 
00950       //TCP socket?
00951       if(socketTable[i].type == SOCKET_TYPE_STREAM)
00952       {
00953          //Check local IP address
00954          if(socket->localIpAddr.length == sizeof(Ipv6Addr))
00955             continue;
00956          if(socket->localIpAddr.ipv4Addr != localIpAddr)
00957             continue;
00958          //Check local port number
00959          if(socket->localPort != localPort)
00960             continue;
00961          //Check remote IP address
00962          if(socket->remoteIpAddr.length == sizeof(Ipv6Addr))
00963             continue;
00964          if(socket->remoteIpAddr.ipv4Addr != remoteIpAddr)
00965             continue;
00966          //Check remote port number
00967          if(socket->remotePort != remotePort)
00968             continue;
00969 
00970          //A matching socket has been found
00971          break;
00972       }
00973    }
00974 
00975    //No matching connection found in socket table?
00976    if(i >= SOCKET_MAX_COUNT)
00977       return ERROR_INSTANCE_NOT_FOUND;
00978 
00979    //tcpConnState object?
00980    if(!strcmp(object->name, "tcpConnState"))
00981    {
00982       //Get object value
00983       switch(socket->state)
00984       {
00985       case TCP_STATE_CLOSED:
00986          value->integer = MIB2_TCP_CONN_STATE_CLOSED;
00987          break;
00988       case TCP_STATE_LISTEN:
00989          value->integer = MIB2_TCP_CONN_STATE_LISTEN;
00990          break;
00991       case TCP_STATE_SYN_SENT:
00992          value->integer = MIB2_TCP_CONN_STATE_SYN_SENT;
00993          break;
00994       case TCP_STATE_SYN_RECEIVED:
00995          value->integer = MIB2_TCP_CONN_STATE_SYN_RECEIVED;
00996          break;
00997       case TCP_STATE_ESTABLISHED:
00998          value->integer = MIB2_TCP_CONN_STATE_ESTABLISHED;
00999          break;
01000       case TCP_STATE_FIN_WAIT_1:
01001          value->integer = MIB2_TCP_CONN_STATE_FIN_WAIT_1;
01002          break;
01003       case TCP_STATE_FIN_WAIT_2:
01004          value->integer = MIB2_TCP_CONN_STATE_FIN_WAIT_2;
01005          break;
01006       case TCP_STATE_CLOSE_WAIT:
01007          value->integer = MIB2_TCP_CONN_STATE_CLOSE_WAIT;
01008          break;
01009       case TCP_STATE_LAST_ACK:
01010          value->integer = MIB2_TCP_CONN_STATE_LAST_ACK;
01011          break;
01012       case TCP_STATE_CLOSING:
01013          value->integer = MIB2_TCP_CONN_STATE_CLOSING;
01014          break;
01015       case TCP_STATE_TIME_WAIT:
01016          value->integer = MIB2_TCP_CONN_STATE_TIME_WAIT;
01017          break;
01018       default:
01019          value->integer = 0;
01020          break;
01021       }
01022    }
01023    //tcpConnLocalAddress object?
01024    else if(!strcmp(object->name, "tcpConnLocalAddress"))
01025    {
01026       //Get object value
01027       ipv4CopyAddr(value->ipAddr, &socket->localIpAddr.ipv4Addr);
01028    }
01029    //tcpConnLocalPort object?
01030    else if(!strcmp(object->name, "tcpConnLocalPort"))
01031    {
01032       //Get object value
01033       value->integer = socket->localPort;
01034    }
01035    //tcpConnRemAddress object?
01036    else if(!strcmp(object->name, "tcpConnRemAddress"))
01037    {
01038       //Get object value
01039       ipv4CopyAddr(value->ipAddr, &socket->remoteIpAddr.ipv4Addr);
01040    }
01041    //tcpConnRemPort object?
01042    else if(!strcmp(object->name, "tcpConnRemPort"))
01043    {
01044       //Get object value
01045       value->integer = socket->remotePort;
01046    }
01047    //Unknown object?
01048    else
01049    {
01050       //The specified object does not exist
01051       error = ERROR_OBJECT_NOT_FOUND;
01052    }
01053 
01054    //Return status code
01055    return error;
01056 }
01057 
01058 
01059 /**
01060  * @brief Get next tcpConnEntry object
01061  * @param[in] object Pointer to the MIB object descriptor
01062  * @param[in] oid Object identifier
01063  * @param[in] oidLen Length of the OID, in bytes
01064  * @param[out] nextOid OID of the next object in the MIB
01065  * @param[out] nextOidLen Length of the next object identifier, in bytes
01066  * @return Error code
01067  **/
01068 
01069 error_t mib2GetNextTcpConnEntry(const MibObject *object, const uint8_t *oid,
01070    size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
01071 {
01072    error_t error;
01073    uint_t i;
01074    size_t n;
01075    bool_t acceptable;
01076    Ipv4Addr localIpAddr;
01077    uint16_t localPort;
01078    Ipv4Addr remoteIpAddr;
01079    uint16_t remotePort;
01080    Socket *socket;
01081 
01082    //Initialize variables
01083    localIpAddr = IPV4_UNSPECIFIED_ADDR;
01084    localPort = 0;
01085    remoteIpAddr = IPV4_UNSPECIFIED_ADDR;
01086    remotePort = 0;
01087 
01088    //Make sure the buffer is large enough to hold the OID prefix
01089    if(*nextOidLen < object->oidLen)
01090       return ERROR_BUFFER_OVERFLOW;
01091 
01092    //Copy OID prefix
01093    memcpy(nextOid, object->oid, object->oidLen);
01094 
01095    //Loop through socket descriptors
01096    for(i = 0; i < SOCKET_MAX_COUNT; i++)
01097    {
01098       //Point to current socket
01099       socket = &socketTable[i];
01100 
01101       //TCP socket?
01102       if(socketTable[i].type == SOCKET_TYPE_STREAM)
01103       {
01104          //Filter out IPv6 connections
01105          if(socket->localIpAddr.length != sizeof(Ipv6Addr) &&
01106             socket->remoteIpAddr.length != sizeof(Ipv6Addr))
01107          {
01108             //Append the instance identifier to the OID prefix
01109             n = object->oidLen;
01110 
01111             //The tcpConnLocalAddress is used as 1st instance identifier
01112             error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, socket->localIpAddr.ipv4Addr);
01113             //Any error to report?
01114             if(error)
01115                return error;
01116 
01117             //The tcpConnLocalPort is used as 2nd instance identifier
01118             error = mibEncodePort(nextOid, *nextOidLen, &n, socket->localPort);
01119             //Any error to report?
01120             if(error)
01121                return error;
01122 
01123             //The tcpConnRemAddress is used as 3rd instance identifier
01124             error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, socket->remoteIpAddr.ipv4Addr);
01125             //Any error to report?
01126             if(error)
01127                return error;
01128 
01129             //The tcpConnRemPort is used as 4th instance identifier
01130             error = mibEncodePort(nextOid, *nextOidLen, &n, socket->remotePort);
01131             //Any error to report?
01132             if(error)
01133                return error;
01134 
01135             //Check whether the resulting object identifier lexicographically
01136             //follows the specified OID
01137             if(oidComp(nextOid, n, oid, oidLen) > 0)
01138             {
01139                //Perform lexicographic comparison
01140                if(localPort == 0 && remotePort == 0)
01141                   acceptable = TRUE;
01142                else if(ntohl(socket->localIpAddr.ipv4Addr) < ntohl(localIpAddr))
01143                   acceptable = TRUE;
01144                else if(ntohl(socket->localIpAddr.ipv4Addr) > ntohl(localIpAddr))
01145                   acceptable = FALSE;
01146                else if(socket->localPort < localPort)
01147                   acceptable = TRUE;
01148                else if(socket->localPort > localPort)
01149                   acceptable = FALSE;
01150                else if(ntohl(socket->remoteIpAddr.ipv4Addr) < ntohl(remoteIpAddr))
01151                   acceptable = TRUE;
01152                else if(ntohl(socket->remoteIpAddr.ipv4Addr) > ntohl(remoteIpAddr))
01153                   acceptable = FALSE;
01154                else if(socket->remotePort < remotePort)
01155                   acceptable = TRUE;
01156                else
01157                   acceptable = FALSE;
01158 
01159                //Save the closest object identifier that follows the specified
01160                //OID in lexicographic order
01161                if(acceptable)
01162                {
01163                   localIpAddr = socket->localIpAddr.ipv4Addr;
01164                   localPort = socket->localPort;
01165                   remoteIpAddr = socket->remoteIpAddr.ipv4Addr;
01166                   remotePort = socket->remotePort;
01167                }
01168             }
01169          }
01170       }
01171    }
01172 
01173    //The specified OID does not lexicographically precede the name
01174    //of some object?
01175    if(localPort == 0 && remotePort == 0)
01176       return ERROR_OBJECT_NOT_FOUND;
01177 
01178    //Append the instance identifier to the OID prefix
01179    n = object->oidLen;
01180 
01181    //The tcpConnLocalAddress is used as 1st instance identifier
01182    error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, localIpAddr);
01183    //Any error to report?
01184    if(error)
01185       return error;
01186 
01187    //The tcpConnLocalPort is used as 2nd instance identifier
01188    error = mibEncodePort(nextOid, *nextOidLen, &n, localPort);
01189    //Any error to report?
01190    if(error)
01191       return error;
01192 
01193    //The tcpConnRemAddress is used as 3rd instance identifier
01194    error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, remoteIpAddr);
01195    //Any error to report?
01196    if(error)
01197       return error;
01198 
01199    //The tcpConnRemPort is used as 4th instance identifier
01200    error = mibEncodePort(nextOid, *nextOidLen, &n, remotePort);
01201    //Any error to report?
01202    if(error)
01203       return error;
01204 
01205    //Save the length of the resulting object identifier
01206    *nextOidLen = n;
01207    //Next object found
01208    return NO_ERROR;
01209 }
01210 
01211 
01212 /**
01213  * @brief Get udpEntry object value
01214  * @param[in] object Pointer to the MIB object descriptor
01215  * @param[in] oid Object identifier (object name and instance identifier)
01216  * @param[in] oidLen Length of the OID, in bytes
01217  * @param[out] value Object value
01218  * @param[in,out] valueLen Length of the object value, in bytes
01219  * @return Error code
01220  **/
01221 
01222 error_t mib2GetUdpEntry(const MibObject *object, const uint8_t *oid,
01223    size_t oidLen, MibVariant *value, size_t *valueLen)
01224 {
01225    error_t error;
01226    uint_t i;
01227    size_t n;
01228    Ipv4Addr localIpAddr;
01229    uint16_t localPort;
01230 
01231    //Point to the instance identifier
01232    n = object->oidLen;
01233 
01234    //The udpLocalAddress is used as 1st instance identifier
01235    error = mibDecodeIpv4Addr(oid, oidLen, &n, &localIpAddr);
01236    //Invalid instance identifier?
01237    if(error)
01238       return error;
01239 
01240    //The udpLocalPort is used as 2nd instance identifier
01241    error = mibDecodePort(oid, oidLen, &n, &localPort);
01242    //Invalid instance identifier?
01243    if(error)
01244       return error;
01245 
01246    //Sanity check
01247    if(n != oidLen)
01248       return ERROR_INSTANCE_NOT_FOUND;
01249 
01250    //Loop through socket descriptors
01251    for(i = 0; i < SOCKET_MAX_COUNT; i++)
01252    {
01253       //Point to current socket
01254       Socket *socket = &socketTable[i];
01255 
01256       //UDP socket?
01257       if(socketTable[i].type == SOCKET_TYPE_DGRAM)
01258       {
01259          //Check local IP address
01260          if(socket->localIpAddr.length == sizeof(Ipv6Addr))
01261             continue;
01262          if(socket->localIpAddr.ipv4Addr != localIpAddr)
01263             continue;
01264          //Check local port number
01265          if(socket->localPort != localPort)
01266             continue;
01267 
01268          //A matching socket has been found
01269          break;
01270       }
01271    }
01272 
01273    //No matching connection found in socket table?
01274    if(i >= SOCKET_MAX_COUNT)
01275    {
01276       //Loop through the UDP callback table
01277       for(i = 0; i < UDP_CALLBACK_TABLE_SIZE; i++)
01278       {
01279          //Point to the current entry
01280          UdpRxCallbackDesc *entry = &udpCallbackTable[i];
01281 
01282          //Check whether the entry is currently in used
01283          if(entry->callback != NULL)
01284          {
01285             //Check local port number
01286             if(entry->port == localPort)
01287                break;
01288          }
01289       }
01290 
01291       //No matching connection found in UDP callback table?
01292       if(i >= UDP_CALLBACK_TABLE_SIZE)
01293          return ERROR_INSTANCE_NOT_FOUND;
01294    }
01295 
01296    //udpLocalAddress object?
01297    if(!strcmp(object->name, "udpLocalAddress"))
01298    {
01299       //Get object value
01300       ipv4CopyAddr(value->ipAddr, &localIpAddr);
01301    }
01302    //udpLocalPort object?
01303    else if(!strcmp(object->name, "udpLocalPort"))
01304    {
01305       //Get object value
01306       value->integer = localPort;
01307    }
01308    //Unknown object?
01309    else
01310    {
01311       //The specified object does not exist
01312       error = ERROR_OBJECT_NOT_FOUND;
01313    }
01314 
01315    //Return status code
01316    return error;
01317 }
01318 
01319 
01320 /**
01321  * @brief Get next udpEntry object
01322  * @param[in] object Pointer to the MIB object descriptor
01323  * @param[in] oid Object identifier
01324  * @param[in] oidLen Length of the OID, in bytes
01325  * @param[out] nextOid OID of the next object in the MIB
01326  * @param[out] nextOidLen Length of the next object identifier, in bytes
01327  * @return Error code
01328  **/
01329 
01330 error_t mib2GetNextUdpEntry(const MibObject *object, const uint8_t *oid,
01331    size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
01332 {
01333    error_t error;
01334    uint_t i;
01335    size_t n;
01336    bool_t acceptable;
01337    Ipv4Addr localIpAddr;
01338    uint16_t localPort;
01339 
01340    //Initialize variables
01341    localIpAddr = IPV4_UNSPECIFIED_ADDR;
01342    localPort = 0;
01343 
01344    //Make sure the buffer is large enough to hold the OID prefix
01345    if(*nextOidLen < object->oidLen)
01346       return ERROR_BUFFER_OVERFLOW;
01347 
01348    //Copy OID prefix
01349    memcpy(nextOid, object->oid, object->oidLen);
01350 
01351    //Loop through socket descriptors
01352    for(i = 0; i < SOCKET_MAX_COUNT; i++)
01353    {
01354       //Point to current socket
01355       Socket *socket = &socketTable[i];
01356 
01357       //TCP socket?
01358       if(socketTable[i].type == SOCKET_TYPE_DGRAM)
01359       {
01360          //Filter out IPv6 connections
01361          if(socket->localIpAddr.length != sizeof(Ipv6Addr) &&
01362             socket->remoteIpAddr.length != sizeof(Ipv6Addr))
01363          {
01364             //Append the instance identifier to the OID prefix
01365             n = object->oidLen;
01366 
01367             //The udpLocalAddress is used as 1st instance identifier
01368             error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, socket->localIpAddr.ipv4Addr);
01369             //Any error to report?
01370             if(error)
01371                return error;
01372 
01373             //The udpLocalPort is used as 2nd instance identifier
01374             error = mibEncodePort(nextOid, *nextOidLen, &n, socket->localPort);
01375             //Any error to report?
01376             if(error)
01377                return error;
01378 
01379             //Check whether the resulting object identifier lexicographically
01380             //follows the specified OID
01381             if(oidComp(nextOid, n, oid, oidLen) > 0)
01382             {
01383                //Perform lexicographic comparison
01384                if(localPort == 0)
01385                   acceptable = TRUE;
01386                else if(ntohl(socket->localIpAddr.ipv4Addr) < ntohl(localIpAddr))
01387                   acceptable = TRUE;
01388                else if(ntohl(socket->localIpAddr.ipv4Addr) > ntohl(localIpAddr))
01389                   acceptable = FALSE;
01390                else if(socket->localPort < localPort)
01391                   acceptable = TRUE;
01392                else
01393                   acceptable = FALSE;
01394 
01395                //Save the closest object identifier that follows the specified
01396                //OID in lexicographic order
01397                if(acceptable)
01398                {
01399                   localIpAddr = socket->localIpAddr.ipv4Addr;
01400                   localPort = socket->localPort;
01401                }
01402             }
01403          }
01404       }
01405    }
01406 
01407    //Loop through the UDP callback table
01408    for(i = 0; i < UDP_CALLBACK_TABLE_SIZE; i++)
01409    {
01410       //Point to the current entry
01411       UdpRxCallbackDesc *entry = &udpCallbackTable[i];
01412 
01413       //Check whether the entry is currently in used
01414       if(entry->callback != NULL)
01415       {
01416          //Append the instance identifier to the OID prefix
01417          n = object->oidLen;
01418 
01419          //The udpLocalAddress is used as 1st instance identifier
01420          error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, IPV4_UNSPECIFIED_ADDR);
01421          //Any error to report?
01422          if(error)
01423             return error;
01424 
01425          //The udpLocalPort is used as 2nd instance identifier
01426          error = mibEncodePort(nextOid, *nextOidLen, &n, entry->port);
01427          //Any error to report?
01428          if(error)
01429             return error;
01430 
01431          //Check whether the resulting object identifier lexicographically
01432          //follows the specified OID
01433          if(oidComp(nextOid, n, oid, oidLen) > 0)
01434          {
01435             //Perform lexicographic comparison
01436             if(localPort == 0)
01437                acceptable = TRUE;
01438             else if(ntohl(IPV4_UNSPECIFIED_ADDR) < ntohl(localIpAddr))
01439                acceptable = TRUE;
01440             else if(ntohl(IPV4_UNSPECIFIED_ADDR) > ntohl(localIpAddr))
01441                acceptable = FALSE;
01442             else if(entry->port < localPort)
01443                acceptable = TRUE;
01444             else
01445                acceptable = FALSE;
01446 
01447             //Save the closest object identifier that follows the specified
01448             //OID in lexicographic order
01449             if(acceptable)
01450             {
01451                localIpAddr = IPV4_UNSPECIFIED_ADDR;
01452                localPort = entry->port;
01453             }
01454          }
01455       }
01456    }
01457 
01458    //The specified OID does not lexicographically precede the name
01459    //of some object?
01460    if(localPort == 0)
01461       return ERROR_OBJECT_NOT_FOUND;
01462 
01463    //Append the instance identifier to the OID prefix
01464    n = object->oidLen;
01465 
01466    //The udpLocalAddress is used as 1st instance identifier
01467    error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, localIpAddr);
01468    //Any error to report?
01469    if(error)
01470       return error;
01471 
01472    //The udpLocalPort is used as 2nd instance identifier
01473    error = mibEncodePort(nextOid, *nextOidLen, &n, localPort);
01474    //Any error to report?
01475    if(error)
01476       return error;
01477 
01478    //Save the length of the resulting object identifier
01479    *nextOidLen = n;
01480    //Next object found
01481    return NO_ERROR;
01482 }
01483 
01484 #endif
01485 #endif
01486