/*
 * Note: this file originally auto-generated by mib2c using
 *       version : 1.17 $ of : mfd-data-access.m2c,v $ 
 *
 * $Id$
 */
/*
 * standard Net-SNMP includes 
 */
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>

/*
 * include our parent header 
 */
#include "inetNetToMediaTable.h"


#include "inetNetToMediaTable_data_access.h"

/** @ingroup interface 
 * @addtogroup data_access data_access: Routines to access data
 *
 * These routines are used to locate the data used to satisfy
 * requests.
 * 
 * @{
 */
/**********************************************************************
 **********************************************************************
 ***
 *** Table inetNetToMediaTable
 ***
 **********************************************************************
 **********************************************************************/
/*
 * IP-MIB::inetNetToMediaTable is subid 35 of ip.
 * Its status is Current.
 * OID: .1.3.6.1.2.1.4.35, length: 8
 */

/**
 * initialization for inetNetToMediaTable data access
 *
 * This function is called during startup to allow you to
 * allocate any resources you need for the data table.
 *
 * @param inetNetToMediaTable_reg
 *        Pointer to inetNetToMediaTable_registration
 *
 * @retval MFD_SUCCESS : success.
 * @retval MFD_ERROR   : unrecoverable error.
 */
int
inetNetToMediaTable_init_data(inetNetToMediaTable_registration *
                              inetNetToMediaTable_reg)
{
    DEBUGMSGTL(("verbose:inetNetToMediaTable:inetNetToMediaTable_init_data", "called\n"));

    /*
     * TODO:303:o: Initialize inetNetToMediaTable data.
     */

    return MFD_SUCCESS;
}                               /* inetNetToMediaTable_init_data */

/**
 * container overview
 *
 */

/**
 * container initialization
 *
 * @param container_ptr_ptr A pointer to a container pointer. If you
 *        create a custom container, use this parameter to return it
 *        to the MFD helper. If set to NULL, the MFD helper will
 *        allocate a container for you.
 * @param  cache A pointer to a cache structure. You can set the timeout
 *         and other cache flags using this pointer.
 *
 *  This function is called at startup to allow you to customize certain
 *  aspects of the access method. For the most part, it is for advanced
 *  users. The default code should suffice for most cases. If no custom
 *  container is allocated, the MFD code will create one for your.
 *
 *  This is also the place to set up cache behavior. The default, to
 *  simply set the cache timeout, will work well with the default
 *  container. If you are using a custom container, you may want to
 *  look at the cache helper documentation to see if there are any
 *  flags you want to set.
 *
 * @remark
 *  This would also be a good place to do any initialization needed
 *  for you data source. For example, opening a connection to another
 *  process that will supply the data, opening a database, etc.
 */
void
inetNetToMediaTable_container_init(netsnmp_container **container_ptr_ptr,
                                   netsnmp_cache * cache)
{
    DEBUGMSGTL(("verbose:inetNetToMediaTable:inetNetToMediaTable_container_init", "called\n"));

    if (NULL == container_ptr_ptr) {
        snmp_log(LOG_ERR,
                 "bad container param to inetNetToMediaTable_container_init\n");
        return;
    }

    /*
     * For advanced users, you can use a custom container. If you
     * do not create one, one will be created for you.
     */
    *container_ptr_ptr = NULL;

    if (NULL == cache) {
        snmp_log(LOG_ERR,
                 "bad cache param to inetNetToMediaTable_container_init\n");
        return;
    }

    /*
     * TODO:345:A: Set up inetNetToMediaTable cache properties.
     *
     * Also for advanced users, you can set parameters for the
     * cache. Do not change the magic pointer, as it is used
     * by the MFD helper. To completely disable caching, set
     * cache->enabled to 0.
     */
    cache->timeout = INETNETTOMEDIATABLE_CACHE_TIMEOUT; /* seconds */

    /* We want to manually delete entries in the cache to keep LastUpdated
     * timestamp. */
    cache->flags |= NETSNMP_CACHE_DONT_FREE_BEFORE_LOAD
                    | NETSNMP_CACHE_AUTO_RELOAD;
}                               /* inetNetToMediaTable_container_init */

/**
 * Put all entries with valid !=1 to the list to delete.
 */
static void
_collect_invalid_arp_ctx(inetNetToMediaTable_rowreq_ctx *ctx,
        netsnmp_container *to_delete)
{
    if (ctx->valid)
            ctx->valid = 0;
    else
        CONTAINER_INSERT(to_delete, ctx);
}

/**
 * check entry for update
 */
static void
_add_or_update_arp_entry(netsnmp_arp_entry *arp_entry,
                 netsnmp_container *container)
{
    inetNetToMediaTable_rowreq_ctx *rowreq_ctx, *old;
    int             inetAddressType;

    DEBUGTRACE;

    netsnmp_assert(NULL != arp_entry);
    netsnmp_assert(NULL != container);

    /*
     * convert the addr len to an inetAddressType
     */
    switch (arp_entry->arp_ipaddress_len) {
    case 4:
        inetAddressType = INETADDRESSTYPE_IPV4;
        break;

    case 16:
        inetAddressType = INETADDRESSTYPE_IPV6;
        break;

    default:
        netsnmp_access_arp_entry_free(arp_entry);
        snmp_log(LOG_ERR, "unsupported address type\n");
        return;
    }

    /*
     * allocate an row context and set the index(es), then try to find it in
     * the cache.
     */
    rowreq_ctx = inetNetToMediaTable_allocate_rowreq_ctx(arp_entry, NULL);
    if ((NULL != rowreq_ctx) &&
        (MFD_SUCCESS == inetNetToMediaTable_indexes_set
         (rowreq_ctx, rowreq_ctx->data->if_index, inetAddressType,
          (char *) rowreq_ctx->data->arp_ipaddress,
          rowreq_ctx->data->arp_ipaddress_len))) {

        /* try to find old entry */
        old = CONTAINER_FIND(container, rowreq_ctx);
        if (old != NULL) {
            /* the entry is already there, update it */
            netsnmp_access_arp_entry_update(old->data, arp_entry);
            old->valid = 1; /* do not delete it in following sweep */
            /* delete the auxiliary context we used to find the entry
             * (this deletes also arp_entry) */
            inetNetToMediaTable_release_rowreq_ctx(rowreq_ctx);
        } else {
            /* create new entry and add it to the cache*/
            rowreq_ctx->inetNetToMediaRowStatus = ROWSTATUS_ACTIVE;
            rowreq_ctx->data->arp_last_updated = netsnmp_get_agent_uptime();
            rowreq_ctx->valid = 1; /* do not delete it in following sweep */
            CONTAINER_INSERT(container, rowreq_ctx);
        }
    } else {
        if (rowreq_ctx) {
            snmp_log(LOG_ERR, "error setting index while loading "
                     "inetNetToMediaTable cache.\n");
            inetNetToMediaTable_release_rowreq_ctx(rowreq_ctx);
        } else
            netsnmp_access_arp_entry_free(arp_entry);
    }
}

/**
 * container shutdown
 *
 * @param container_ptr A pointer to the container.
 *
 *  This function is called at shutdown to allow you to customize certain
 *  aspects of the access method. For the most part, it is for advanced
 *  users. The default code should suffice for most cases.
 *
 *  This function is called before inetNetToMediaTable_container_free().
 *
 * @remark
 *  This would also be a good place to do any cleanup needed
 *  for you data source. For example, closing a connection to another
 *  process that supplied the data, closing a database, etc.
 */
void
inetNetToMediaTable_container_shutdown(netsnmp_container *container_ptr)
{
    DEBUGMSGTL(("verbose:inetNetToMediaTable:inetNetToMediaTable_container_shutdown", "called\n"));

    if (NULL == container_ptr) {
        snmp_log(LOG_ERR,
                 "bad params to inetNetToMediaTable_container_shutdown\n");
        return;
    }

}                               /* inetNetToMediaTable_container_shutdown */

/**
 * load initial data
 *
 * TODO:350:M: Implement inetNetToMediaTable data load
 * This function will also be called by the cache helper to load
 * the container again (after the container free function has been
 * called to free the previous contents).
 *
 * @param container container to which items should be inserted
 *
 * @retval MFD_SUCCESS              : success.
 * @retval MFD_RESOURCE_UNAVAILABLE : Can't access data source
 * @retval MFD_ERROR                : other error.
 *
 *  This function is called to load the index(es) (and data, optionally)
 *  for the every row in the data set.
 *
 * @remark
 *  While loading the data, the only important thing is the indexes.
 *  If access to your data is cheap/fast (e.g. you have a pointer to a
 *  structure in memory), it would make sense to update the data here.
 *  If, however, the accessing the data invovles more work (e.g. parsing
 *  some other existing data, or peforming calculations to derive the data),
 *  then you can limit yourself to setting the indexes and saving any
 *  information you will need later. Then use the saved information in
 *  inetNetToMediaTable_row_prep() for populating data.
 *
 * @note
 *  If you need consistency between rows (like you want statistics
 *  for each row to be from the same time frame), you should set all
 *  data here.
 *
 */
int
inetNetToMediaTable_container_load(netsnmp_container *container)
{
    netsnmp_container *arp_container;
    netsnmp_container *to_delete = netsnmp_container_find("lifo");

    DEBUGMSGTL(("verbose:inetNetToMediaTable:inetNetToMediaTable_cache_load", "called\n"));

    /*
     * TODO:351:M: |-> Load/update data in the inetNetToMediaTable container.
     * loop over your inetNetToMediaTable data, allocate a rowreq context,
     * set the index(es) [and data, optionally] and insert into
     * the container.
     */
    arp_container =
        netsnmp_access_arp_container_load(NULL,
                                          NETSNMP_ACCESS_ARP_LOAD_NOFLAGS);
    if (NULL == arp_container)
        return MFD_RESOURCE_UNAVAILABLE;        /* msg already logged */

    /*
     * we just got a fresh copy of data. snarf data
     */
    CONTAINER_FOR_EACH(arp_container,
                       (netsnmp_container_obj_func *) _add_or_update_arp_entry,
                       container);

    /*
     * Delete all cached entries, which were not provided by
     * netsnmp_access_arp_container_load
     */
    CONTAINER_FOR_EACH(container,
                       (netsnmp_container_obj_func *) _collect_invalid_arp_ctx,
                       to_delete);
    while (CONTAINER_SIZE(to_delete)) {
        inetNetToMediaTable_rowreq_ctx *ctx = CONTAINER_FIRST(to_delete);
        CONTAINER_REMOVE(container, ctx);
        inetNetToMediaTable_release_rowreq_ctx(ctx);
        CONTAINER_REMOVE(to_delete, NULL);
    }
    CONTAINER_FREE(to_delete);

    /*
     * free the container. we've either claimed each entry, or released it,
     * so the access function doesn't need to clear the container.
     */
    netsnmp_access_arp_container_free(arp_container,
                                      NETSNMP_ACCESS_ARP_FREE_DONT_CLEAR);

    DEBUGMSGT(("verbose:inetNetToMediaTable:inetNetToMediaTable_cache_load",
               "%" NETSNMP_PRIz "u records\n", CONTAINER_SIZE(container)));

    return MFD_SUCCESS;
}                               /* inetNetToMediaTable_container_load */

/**
 * container clean up
 *
 * @param container container with all current items
 *
 *  This optional callback is called prior to all
 *  item's being removed from the container. If you
 *  need to do any processing before that, do it here.
 *
 * @note
 *  The MFD helper will take care of releasing all the row contexts.
 *
 */
void
inetNetToMediaTable_container_free(netsnmp_container *container)
{
    DEBUGMSGTL(("verbose:inetNetToMediaTable:inetNetToMediaTable_container_free", "called\n"));

    /*
     * TODO:380:M: Free inetNetToMediaTable container data.
     */
}                               /* inetNetToMediaTable_container_free */

/**
 * prepare row for processing.
 *
 *  When the agent has located the row for a request, this function is
 *  called to prepare the row for processing. If you fully populated
 *  the data context during the index setup phase, you may not need to
 *  do anything.
 *
 * @param rowreq_ctx pointer to a context.
 *
 * @retval MFD_SUCCESS     : success.
 * @retval MFD_ERROR       : other error.
 */
int
inetNetToMediaTable_row_prep(inetNetToMediaTable_rowreq_ctx * rowreq_ctx)
{
    DEBUGMSGTL(("verbose:inetNetToMediaTable:inetNetToMediaTable_row_prep",
                "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:390:o: Prepare row for request.
     * If populating row data was delayed, this is the place to
     * fill in the row for this request.
     */

    return MFD_SUCCESS;
}                               /* inetNetToMediaTable_row_prep */

/*
 * TODO:420:r: Implement inetNetToMediaTable index validation.
 */
/*---------------------------------------------------------------------
 * IP-MIB::inetNetToMediaEntry.inetNetToMediaIfIndex
 * inetNetToMediaIfIndex is subid 1 of inetNetToMediaEntry.
 * Its status is Current, and its access level is NoAccess.
 * OID: .1.3.6.1.2.1.4.35.1.1
 * Description:
The index value which uniquely identifies the interface to
            which this entry is applicable.  The interface identified by
            a particular value of this index is the same interface as
            identified by the same value of the IF-MIB's ifIndex.
 *
 * Attributes:
 *   accessible 0     isscalar 0     enums  0      hasdefval 0
 *   readable   0     iscolumn 1     ranges 1      hashint   1
 *   settable   0
 *   hint: d
 *
 * Ranges:  1 - 2147483647;
 *
 * Its syntax is InterfaceIndex (based on perltype INTEGER32)
 * The net-snmp type is ASN_INTEGER. The C type decl is long (long)
 *
 *
 *
 * NOTE: NODE inetNetToMediaIfIndex IS NOT ACCESSIBLE
 *
 *
 */
/**
 * check validity of inetNetToMediaIfIndex index portion
 *
 * @retval MFD_SUCCESS   : the incoming value is legal
 * @retval MFD_ERROR     : the incoming value is NOT legal
 *
 * @note this is not the place to do any checks for the sanity
 *       of multiple indexes. Those types of checks should be done in the
 *       inetNetToMediaTable_validate_index() function.
 *
 * @note Also keep in mind that if the index refers to a row in this or
 *       some other table, you can't check for that row here to make
 *       decisions, since that row might not be created yet, but may
 *       be created during the processing this request. If you have
 *       such checks, they should be done in the check_dependencies
 *       function, because any new/deleted/changed rows should be
 *       available then.
 *
 * The following checks have already been done for you:
 *    The value is in (one of) the range set(s):  1 - 2147483647
 *
 * If there a no other checks you need to do, simply return MFD_SUCCESS.
 */
int
inetNetToMediaIfIndex_check_index(inetNetToMediaTable_rowreq_ctx *
                                  rowreq_ctx)
{
    DEBUGMSGTL(("verbose:inetNetToMediaTable:inetNetToMediaIfIndex_check_index", "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:426:M: |-> Check inetNetToMediaTable index inetNetToMediaIfIndex.
     * check that index value in the table context is legal.
     * (rowreq_ctx->tbl_index.inetNetToMediaIfIndex)
     */

    return MFD_SUCCESS;         /* inetNetToMediaIfIndex index ok */
}                               /* inetNetToMediaIfIndex_check_index */

/*---------------------------------------------------------------------
 * IP-MIB::inetNetToMediaEntry.inetNetToMediaNetAddressType
 * inetNetToMediaNetAddressType is subid 2 of inetNetToMediaEntry.
 * Its status is Current, and its access level is NoAccess.
 * OID: .1.3.6.1.2.1.4.35.1.2
 * Description:
The type of inetNetToMediaNetAddress.
 *
 * Attributes:
 *   accessible 0     isscalar 0     enums  1      hasdefval 0
 *   readable   0     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 * Enum range: 5/8. Values:  unknown(0), ipv4(1), ipv6(2), ipv4z(3), ipv6z(4), dns(16)
 *
 * Its syntax is InetAddressType (based on perltype INTEGER)
 * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
 *
 *
 *
 * NOTE: NODE inetNetToMediaNetAddressType IS NOT ACCESSIBLE
 *
 *
 */
/**
 * check validity of inetNetToMediaNetAddressType index portion
 *
 * @retval MFD_SUCCESS   : the incoming value is legal
 * @retval MFD_ERROR     : the incoming value is NOT legal
 *
 * @note this is not the place to do any checks for the sanity
 *       of multiple indexes. Those types of checks should be done in the
 *       inetNetToMediaTable_validate_index() function.
 *
 * @note Also keep in mind that if the index refers to a row in this or
 *       some other table, you can't check for that row here to make
 *       decisions, since that row might not be created yet, but may
 *       be created during the processing this request. If you have
 *       such checks, they should be done in the check_dependencies
 *       function, because any new/deleted/changed rows should be
 *       available then.
 *
 * The following checks have already been done for you:
 *    The value is one of  unknown(0), ipv4(1), ipv6(2), ipv4z(3), ipv6z(4), dns(16)
 *
 * If there a no other checks you need to do, simply return MFD_SUCCESS.
 */
int
inetNetToMediaNetAddressType_check_index(inetNetToMediaTable_rowreq_ctx *
                                         rowreq_ctx)
{
    DEBUGMSGTL(("verbose:inetNetToMediaTable:inetNetToMediaNetAddressType_check_index", "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:426:M: |-> Check inetNetToMediaTable index inetNetToMediaNetAddressType.
     * check that index value in the table context is legal.
     * (rowreq_ctx->tbl_index.inetNetToMediaNetAddressType)
     */

    return MFD_SUCCESS;         /* inetNetToMediaNetAddressType index ok */
}                               /* inetNetToMediaNetAddressType_check_index */

/*---------------------------------------------------------------------
 * IP-MIB::inetNetToMediaEntry.inetNetToMediaNetAddress
 * inetNetToMediaNetAddress is subid 3 of inetNetToMediaEntry.
 * Its status is Current, and its access level is NoAccess.
 * OID: .1.3.6.1.2.1.4.35.1.3
 * Description:
The IP Address corresponding to the media-dependent
            `physical' address.  The address type of this object is
            specified in inetNetToMediaAddressType.


            Implementors need to be aware that if the size of
            inetNetToMediaNetAddress exceeds 115 octets then OIDS of
            instances of columns in this row will have more than 128
            sub-identifiers and cannot be accessed using SNMPv1, SNMPv2c
            or SNMPv3.
 *
 * Attributes:
 *   accessible 0     isscalar 0     enums  0      hasdefval 0
 *   readable   0     iscolumn 1     ranges 1      hashint   0
 *   settable   0
 *
 * Ranges:  0 - 255;
 *
 * Its syntax is InetAddress (based on perltype OCTETSTR)
 * The net-snmp type is ASN_OCTET_STR. The C type decl is char (char)
 * This data type requires a length.  (Max 255)
 *
 *
 *
 * NOTE: NODE inetNetToMediaNetAddress IS NOT ACCESSIBLE
 *
 *
 */
/**
 * check validity of inetNetToMediaNetAddress index portion
 *
 * @retval MFD_SUCCESS   : the incoming value is legal
 * @retval MFD_ERROR     : the incoming value is NOT legal
 *
 * @note this is not the place to do any checks for the sanity
 *       of multiple indexes. Those types of checks should be done in the
 *       inetNetToMediaTable_validate_index() function.
 *
 * @note Also keep in mind that if the index refers to a row in this or
 *       some other table, you can't check for that row here to make
 *       decisions, since that row might not be created yet, but may
 *       be created during the processing this request. If you have
 *       such checks, they should be done in the check_dependencies
 *       function, because any new/deleted/changed rows should be
 *       available then.
 *
 * The following checks have already been done for you:
 *    The length is in (one of) the range set(s):  0 - 255
 *
 * If there a no other checks you need to do, simply return MFD_SUCCESS.
 */
int
inetNetToMediaNetAddress_check_index(inetNetToMediaTable_rowreq_ctx *
                                     rowreq_ctx)
{
    DEBUGMSGTL(("verbose:inetNetToMediaTable:inetNetToMediaNetAddress_check_index", "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:426:M: |-> Check inetNetToMediaTable index inetNetToMediaNetAddress.
     * check that index value in the table context is legal.
     * (rowreq_ctx->tbl_index.inetNetToMediaNetAddress)
     */

    return MFD_SUCCESS;         /* inetNetToMediaNetAddress index ok */
}                               /* inetNetToMediaNetAddress_check_index */

/**
 * verify specified index is valid.
 *
 * This check is independent of whether or not the values specified for
 * the columns of the new row are valid. Column values and row consistency
 * will be checked later. At this point, only the index values should be
 * checked.
 *
 * All of the individual index validation functions have been called, so this
 * is the place to make sure they are valid as a whole when combined. If
 * you only have one index, then you probably don't need to do anything else
 * here.
 * 
 * @note Keep in mind that if the indexes refer to a row in this or
 *       some other table, you can't check for that row here to make
 *       decisions, since that row might not be created yet, but may
 *       be created during the processing this request. If you have
 *       such checks, they should be done in the check_dependencies
 *       function, because any new/deleted/changed rows should be
 *       available then.
 *
 *
 * @param inetNetToMediaTable_reg
 *        Pointer to the user registration data
 * @param rowreq_ctx
 *        Pointer to the users context.
 * @retval MFD_SUCCESS            : success
 * @retval MFD_CANNOT_CREATE_NOW  : index not valid right now
 * @retval MFD_CANNOT_CREATE_EVER : index never valid
 */
int
inetNetToMediaTable_validate_index(inetNetToMediaTable_registration *
                                   inetNetToMediaTable_reg,
                                   inetNetToMediaTable_rowreq_ctx *
                                   rowreq_ctx)
{
    int             rc = MFD_SUCCESS;

    DEBUGMSGTL(("verbose:inetNetToMediaTable:inetNetToMediaTable_validate_index", "called\n"));

    /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:430:M: |-> Validate potential inetNetToMediaTable index.
     */
    if (1) {
        snmp_log(LOG_WARNING, "invalid index for a new row in the "
                 "inetNetToMediaTable table.\n");
        /*
         * determine failure type.
         *
         * If the index could not ever be created, return MFD_NOT_EVER
         * If the index can not be created under the present circumstances
         * (even though it could be created under other circumstances),
         * return MFD_NOT_NOW.
         */
        if (0) {
            return MFD_CANNOT_CREATE_EVER;
        } else {
            return MFD_CANNOT_CREATE_NOW;
        }
    }

    return rc;
}                               /* inetNetToMediaTable_validate_index */

/** @} */
