/*
 * Note: this file originally auto-generated by mib2c using
 *       version : 1.32 $ of : mfd-top.m2c,v $ 
 *
 * $Id: ifXTable.c,v 1.12.2.1 2004/12/10 18:01:33 rstory Exp $
 */
/** \mainpage MFD helper for ifXTable
 *
 * \section intro Introduction
 * Introductory text.
 *
 */
/*
 * 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 <ctype.h>

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

#include <net-snmp/agent/mib_modules.h>

#include "ifXTable_interface.h"

#define LINE_TERM_CHAR '$'

/*
 * not sure if we want to support set for promiscuous mode, because
 * 1) careful thought should go into any settable object that performs
 *    an action that requires root access
 * 2) i don't want to write the code right now
 * 
 */
#undef NETSNMP_ENABLE_PROMISCUOUSMODE_SET

oid             ifXTable_oid[] = { IFXTABLE_OID };
int             ifXTable_oid_size = OID_LENGTH(ifXTable_oid);
const char     *row_token = "ifXTable";

void            initialize_table_ifXTable(void);

static void     _ifXTable_restore(const char *token, char *buf);
static int      _ifXTable_save(int majorID, int minorID, void *serverarg,
                               void *clientarg);

extern netsnmp_container *_ifXTable_container_get(void);

/**
 * Initializes the ifXTable module
 */
void
init_ifXTable(void)
{
    DEBUGMSGTL(("verbose:ifXTable:init_ifXTable", "called\n"));

    /*
     * TODO:300:o: Perform ifXTable one-time module initialization.
     */

    /*
     * here we initialize all the tables we're planning on supporting
     */
    if (should_init("ifXTable"))
        initialize_table_ifXTable();

}                               /* init_ifXTable */

/**
 * Initialize the table ifXTable 
 *    (Define its contents and how it's structured)
 */
void
initialize_table_ifXTable(void)
{
    ifXTable_registration_ptr user_context;
    u_long          flags;
    int             rc;

    DEBUGMSGTL(("verbose:ifXTable:initialize_table_ifXTable", "called\n"));

    /*
     * TODO:301:o: Perform ifXTable one-time table initialization.
     */

    /*
     * TODO:302:o: |->Initialize ifXTable user context
     * if you'd like to pass in a pointer to some data for this
     * table, allocate or set it up here.
     */
    /*
     * a netsnmp_data_list is a simple way to store void pointers. A simple
     * string token is used to add, find or remove pointers.
     */
    user_context = netsnmp_create_data_list("ifXTable", NULL, NULL);

    /*
     * No support for any flags yet, but in the future you would
     * set any flags here.
     */
    flags = 0;

    /*
     * call interface initialization code
     */
    _ifXTable_initialize_interface(user_context, flags);

    /*
     * if there is no container, bail. otherwise, register the callbacks
     * for persistent storage.
     */
    if (NULL == _ifXTable_container_get())
        return; /* msg already logged */

    register_config_handler(NULL, "ifXTable", _ifXTable_restore, NULL,
                            NULL);
    rc = snmp_register_callback(SNMP_CALLBACK_LIBRARY,
                                SNMP_CALLBACK_STORE_DATA, _ifXTable_save,
                                _ifXTable_container_get());
    if (rc != SNMP_ERR_NOERROR)
        snmp_log(LOG_ERR, "error registering for STORE_DATA callback "
                 "in initialize_table_ifXTable\n");

}                               /* initialize_table_ifXTable */

/**
 * extra context initialization
 *
 * @param rowreq_ctx    : row request context
 * @param user_init_ctx : void pointer for user (parameter to rowreq_ctx_allocate)
 *
 * @retval MFD_SUCCESS  : no errors
 * @retval MFD_ERROR    : error (context allocate will fail)
 */
int
ifXTable_rowreq_ctx_init(ifXTable_rowreq_ctx * rowreq_ctx,
                         void *user_init_ctx)
{
    DEBUGMSGTL(("verbose:ifXTable:ifXTable_rowreq_ctx_init", "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:210:o: |-> Perform extra ifXTable rowreq initialization.
     * should never get here - ifTable should handle this
     */
    netsnmp_assert(0);

    return MFD_SUCCESS;
}                               /* ifXTable_rowreq_ctx_init */

/**
 * extra context cleanup
 *
 */
void
ifXTable_rowreq_ctx_cleanup(ifXTable_rowreq_ctx * rowreq_ctx)
{
    DEBUGMSGTL(("verbose:ifXTable:ifXTable_rowreq_ctx_cleanup",
                "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:211:o: |-> Perform extra ifXTable rowreq cleanup.
     */
    /*
     * should never get here - ifTable should handle this
     */
    netsnmp_assert(0);
}                               /* ifXTable_rowreq_ctx_cleanup */

/**
 * pre-request callback
 *
 *
 * @retval MFD_SUCCESS              : success.
 * @retval MFD_ERROR                : other error
 */
int
ifXTable_pre_request(ifXTable_registration_ptr user_context)
{
    DEBUGMSGTL(("verbose:ifXTable:ifXTable_pre_request", "called\n"));

    /*
     * TODO:510:o: Perform ifXTable pre-request actions.
     */

    return MFD_SUCCESS;
}                               /* ifXTable_pre_request */

/**
 * post-request callback
 *
 *
 * @retval MFD_SUCCESS : success.
 * @retval MFD_ERROR   : other error (ignored)
 */
int
ifXTable_post_request(ifXTable_registration_ptr user_context)
{
    DEBUGMSGTL(("verbose:ifXTable:ifXTable_post_request", "called\n"));

    /*
     * TODO:511:o: Perform ifXTable pos-request actions.
     */

    return MFD_SUCCESS;
}                               /* ifXTable_post_request */


/**********************************************************************
 **********************************************************************
 ***
 *** Table ifXTable
 ***
 **********************************************************************
 **********************************************************************/
/*
 * ifXTable is subid 1 of ifMIBObjects.
 * Its status is Current.
 * OID: .1.3.6.1.2.1.31.1.1, length: 9
 */



/**
 * set mib index(es)
 *
 * @param tbl_idx mib index structure
 *
 * @retval MFD_SUCCESS     : success.
 * @retval MFD_ERROR       : other error.
 *
 * @remark
 *  This convenience function is useful for setting all the MIB index
 *  components with a single function call. It is assume that the C values
 *  have already been mapped from their native/rawformat to the MIB format.
 */
int
ifXTable_indexes_set_tbl_idx(ifXTable_mib_index * tbl_idx,
                             long ifIndex_val)
{
    DEBUGMSGTL(("verbose:ifXTable:ifXTable_indexes_set_tbl_idx",
                "called\n"));

    /*
     * ifIndex(1)/InterfaceIndex/ASN_INTEGER/long(long)//l/A/w/e/R/d/H 
     */
    tbl_idx->ifIndex = ifIndex_val;


    return MFD_SUCCESS;
}                               /* ifXTable_indexes_set_tbl_idx */

/**
 * @internal
 * set row context indexes
 *
 * @param reqreq_ctx the row context that needs updated indexes
 *
 * @retval MFD_SUCCESS     : success.
 * @retval MFD_ERROR       : other error.
 *
 * @remark
 *  This function sets the mib indexs, then updates the oid indexs
 *  from the mib index.
 */
int
ifXTable_indexes_set(ifXTable_rowreq_ctx * rowreq_ctx, long ifIndex_val)
{
    DEBUGMSGTL(("verbose:ifXTable:ifXTable_indexes_set", "called\n"));

    if (MFD_SUCCESS !=
        ifXTable_indexes_set_tbl_idx(&rowreq_ctx->tbl_idx, ifIndex_val))
        return MFD_ERROR;

    /*
     * convert mib index to oid index
     */
    rowreq_ctx->oid_idx.len = sizeof(rowreq_ctx->oid_tmp) / sizeof(oid);
    if (0 != ifXTable_index_to_oid(&rowreq_ctx->oid_idx,
                                   &rowreq_ctx->tbl_idx)) {
        return MFD_ERROR;
    }

    return MFD_SUCCESS;
}                               /* ifXTable_indexes_set */


/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifName
 * ifName is subid 1 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.1
 * Description:
The textual name of the interface.  The value of this
            object should be the name of the interface as assigned by
            the local device and should be suitable for use in commands
            entered at the device's `console'.  This might be a text
            name, such as `le0' or a simple port number, such as `1',
            depending on the interface naming syntax of the device.  If
            several entries in the ifTable together represent a single
            interface as named by the device, then each will have the
            same value of ifName.  Note that for an agent which responds
            to SNMP queries concerning an interface on some other
            (proxied) device, then the value of ifName for such an
            interface is the proxied device's local name for it.

            If there is no local name, or this object is otherwise not
            applicable, then this object contains a zero-length string.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 1      hashint   1
 *   settable   0
 *   hint: 255a
 *
 * Ranges:  0 - 255;
 *
 * Its syntax is DisplayString (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)
 */
/**
 * Extract the current value of the ifName data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifName_val_ptr_ptr
 *        Pointer to storage for a char variable
 * @param ifName_val_ptr_len_ptr
 *        Pointer to a size_t. On entry, it will contain the size (in bytes)
 *        pointed to by ifName.
 *        On exit, this value should contain the data size (in bytes).
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
*
 * @note If you need more than (*ifName_val_ptr_len_ptr) bytes of memory,
 *       allocate it using malloc() and update ifName_val_ptr_ptr.
 *       <b>DO NOT</b> free the previous pointer.
 *       The MFD helper will release the memory you allocate.
 *
 * @remark If you call this function yourself, you are responsible
 *         for checking if the pointer changed, and freeing any
 *         previously allocated memory. (Not necessary if you pass
 *         in a pointer to static memory, obviously.)
 */
int
ifName_get(ifXTable_rowreq_ctx * rowreq_ctx, char **ifName_val_ptr_ptr,
           size_t *ifName_val_ptr_len_ptr)
{
    int             tmp_len;
   /** we should have a non-NULL pointer and enough storage */
    netsnmp_assert((NULL != ifName_val_ptr_ptr)
                   && (NULL != *ifName_val_ptr_ptr));
    netsnmp_assert(NULL != ifName_val_ptr_len_ptr);


    DEBUGMSGTL(("verbose:ifXTable:ifName_get", "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:231:o: |-> Extract the current value of the ifName data.
     * set (* ifName_val_ptr_ptr ) and (* ifName_val_ptr_len_ptr ) from rowreq_ctx->data
     */
    /*
     * make sure there is enough space for ifName data
     */
    tmp_len = strlen(rowreq_ctx->data.ifName);
    if ((NULL == (*ifName_val_ptr_ptr))
        || ((*ifName_val_ptr_len_ptr) < tmp_len)) {
        /*
         * allocate space for ifName data
         */
        (*ifName_val_ptr_ptr) =
            malloc(tmp_len * sizeof((*ifName_val_ptr_ptr)[0]));
        if (NULL == (*ifName_val_ptr_ptr)) {
            snmp_log(LOG_ERR, "could not allocate memory\n");
            return MFD_ERROR;
        }
    }
    (*ifName_val_ptr_len_ptr) = tmp_len;
    memcpy((*ifName_val_ptr_ptr), rowreq_ctx->data.ifName,
           (*ifName_val_ptr_len_ptr) * sizeof((*ifName_val_ptr_ptr)[0]));

    return MFD_SUCCESS;
}                               /* ifName_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifInMulticastPkts
 * ifInMulticastPkts is subid 2 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.2
 * Description:
The number of packets, delivered by this sub-layer to a
            higher (sub-)layer, which were addressed to a multicast
            address at this sub-layer.  For a MAC layer protocol, this
            includes both Group and Functional addresses.

            Discontinuities in the value of this counter can occur at
            re-initialization of the management system, and at other

            times as indicated by the value of
            ifCounterDiscontinuityTime.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 *
 * Its syntax is COUNTER (based on perltype COUNTER)
 * The net-snmp type is ASN_COUNTER. The C type decl is u_long (u_long)
 */
/**
 * Extract the current value of the ifInMulticastPkts data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifInMulticastPkts_val_ptr
 *        Pointer to storage for a u_long variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifInMulticastPkts_get(ifXTable_rowreq_ctx * rowreq_ctx,
                      u_long * ifInMulticastPkts_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifInMulticastPkts_val_ptr);


    DEBUGMSGTL(("verbose:ifXTable:ifInMulticastPkts_get", "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:231:o: |-> Extract the current value of the ifInMulticastPkts data.
     * set (* ifInMulticastPkts_val_ptr ) from rowreq_ctx->data
     */
    (*ifInMulticastPkts_val_ptr) = rowreq_ctx->data.ifInMulticastPkts;

    return MFD_SUCCESS;
}                               /* ifInMulticastPkts_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifInBroadcastPkts
 * ifInBroadcastPkts is subid 3 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.3
 * Description:
The number of packets, delivered by this sub-layer to a
            higher (sub-)layer, which were addressed to a broadcast
            address at this sub-layer.

            Discontinuities in the value of this counter can occur at
            re-initialization of the management system, and at other
            times as indicated by the value of
            ifCounterDiscontinuityTime.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 *
 * Its syntax is COUNTER (based on perltype COUNTER)
 * The net-snmp type is ASN_COUNTER. The C type decl is u_long (u_long)
 */
/**
 * Extract the current value of the ifInBroadcastPkts data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifInBroadcastPkts_val_ptr
 *        Pointer to storage for a u_long variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifInBroadcastPkts_get(ifXTable_rowreq_ctx * rowreq_ctx,
                      u_long * ifInBroadcastPkts_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifInBroadcastPkts_val_ptr);


    DEBUGMSGTL(("verbose:ifXTable:ifInBroadcastPkts_get", "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:231:o: |-> Extract the current value of the ifInBroadcastPkts data.
     * set (* ifInBroadcastPkts_val_ptr ) from rowreq_ctx->data
     */
    (*ifInBroadcastPkts_val_ptr) = rowreq_ctx->data.ifInBroadcastPkts;

    return MFD_SUCCESS;
}                               /* ifInBroadcastPkts_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifOutMulticastPkts
 * ifOutMulticastPkts is subid 4 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.4
 * Description:
The total number of packets that higher-level protocols
            requested be transmitted, and which were addressed to a
            multicast address at this sub-layer, including those that
            were discarded or not sent.  For a MAC layer protocol, this
            includes both Group and Functional addresses.

            Discontinuities in the value of this counter can occur at
            re-initialization of the management system, and at other
            times as indicated by the value of
            ifCounterDiscontinuityTime.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 *
 * Its syntax is COUNTER (based on perltype COUNTER)
 * The net-snmp type is ASN_COUNTER. The C type decl is u_long (u_long)
 */
/**
 * Extract the current value of the ifOutMulticastPkts data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifOutMulticastPkts_val_ptr
 *        Pointer to storage for a u_long variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifOutMulticastPkts_get(ifXTable_rowreq_ctx * rowreq_ctx,
                       u_long * ifOutMulticastPkts_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifOutMulticastPkts_val_ptr);


    DEBUGMSGTL(("verbose:ifXTable:ifOutMulticastPkts_get", "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:231:o: |-> Extract the current value of the ifOutMulticastPkts data.
     * set (* ifOutMulticastPkts_val_ptr ) from rowreq_ctx->data
     */
    (*ifOutMulticastPkts_val_ptr) = rowreq_ctx->data.ifOutMulticastPkts;

    return MFD_SUCCESS;
}                               /* ifOutMulticastPkts_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifOutBroadcastPkts
 * ifOutBroadcastPkts is subid 5 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.5
 * Description:
The total number of packets that higher-level protocols
            requested be transmitted, and which were addressed to a
            broadcast address at this sub-layer, including those that
            were discarded or not sent.

            Discontinuities in the value of this counter can occur at
            re-initialization of the management system, and at other

            times as indicated by the value of
            ifCounterDiscontinuityTime.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 *
 * Its syntax is COUNTER (based on perltype COUNTER)
 * The net-snmp type is ASN_COUNTER. The C type decl is u_long (u_long)
 */
/**
 * Extract the current value of the ifOutBroadcastPkts data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifOutBroadcastPkts_val_ptr
 *        Pointer to storage for a u_long variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifOutBroadcastPkts_get(ifXTable_rowreq_ctx * rowreq_ctx,
                       u_long * ifOutBroadcastPkts_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifOutBroadcastPkts_val_ptr);


    DEBUGMSGTL(("verbose:ifXTable:ifOutBroadcastPkts_get", "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:231:o: |-> Extract the current value of the ifOutBroadcastPkts data.
     * set (* ifOutBroadcastPkts_val_ptr ) from rowreq_ctx->data
     */
    (*ifOutBroadcastPkts_val_ptr) = rowreq_ctx->data.ifOutBroadcastPkts;

    return MFD_SUCCESS;
}                               /* ifOutBroadcastPkts_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifHCInOctets
 * ifHCInOctets is subid 6 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.6
 * Description:
The total number of octets received on the interface,
            including framing characters.  This object is a 64-bit
            version of ifInOctets.

            Discontinuities in the value of this counter can occur at
            re-initialization of the management system, and at other
            times as indicated by the value of
            ifCounterDiscontinuityTime.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 *
 * Its syntax is COUNTER64 (based on perltype COUNTER64)
 * The net-snmp type is ASN_COUNTER64. The C type decl is U64 (U64)
 */
/**
 * Extract the current value of the ifHCInOctets data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifHCInOctets_val_ptr
 *        Pointer to storage for a U64 variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifHCInOctets_get(ifXTable_rowreq_ctx * rowreq_ctx,
                 U64 * ifHCInOctets_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifHCInOctets_val_ptr);

    /*
     * TODO:231:o: |-> copy ifHCInOctets data.
     * get (* ifHCInOctets_val_ptr ).low and (* ifHCInOctets_val_ptr ).high from rowreq_ctx->data
     */
    (*ifHCInOctets_val_ptr).high = rowreq_ctx->data.ifHCInOctets.high;
    (*ifHCInOctets_val_ptr).low = rowreq_ctx->data.ifHCInOctets.low;


    return MFD_SUCCESS;
}                               /* ifHCInOctets_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifHCInUcastPkts
 * ifHCInUcastPkts is subid 7 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.7
 * Description:
The number of packets, delivered by this sub-layer to a
            higher (sub-)layer, which were not addressed to a multicast
            or broadcast address at this sub-layer.  This object is a
            64-bit version of ifInUcastPkts.

            Discontinuities in the value of this counter can occur at
            re-initialization of the management system, and at other
            times as indicated by the value of
            ifCounterDiscontinuityTime.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 *
 * Its syntax is COUNTER64 (based on perltype COUNTER64)
 * The net-snmp type is ASN_COUNTER64. The C type decl is U64 (U64)
 */
/**
 * Extract the current value of the ifHCInUcastPkts data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifHCInUcastPkts_val_ptr
 *        Pointer to storage for a U64 variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifHCInUcastPkts_get(ifXTable_rowreq_ctx * rowreq_ctx,
                    U64 * ifHCInUcastPkts_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifHCInUcastPkts_val_ptr);

    /*
     * TODO:231:o: |-> copy ifHCInUcastPkts data.
     * get (* ifHCInUcastPkts_val_ptr ).low and (* ifHCInUcastPkts_val_ptr ).high from rowreq_ctx->data
     */
    (*ifHCInUcastPkts_val_ptr).high =
        rowreq_ctx->data.ifHCInUcastPkts.high;
    (*ifHCInUcastPkts_val_ptr).low = rowreq_ctx->data.ifHCInUcastPkts.low;


    return MFD_SUCCESS;
}                               /* ifHCInUcastPkts_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifHCInMulticastPkts
 * ifHCInMulticastPkts is subid 8 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.8
 * Description:
The number of packets, delivered by this sub-layer to a
            higher (sub-)layer, which were addressed to a multicast
            address at this sub-layer.  For a MAC layer protocol, this
            includes both Group and Functional addresses.  This object
            is a 64-bit version of ifInMulticastPkts.

            Discontinuities in the value of this counter can occur at
            re-initialization of the management system, and at other
            times as indicated by the value of
            ifCounterDiscontinuityTime.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 *
 * Its syntax is COUNTER64 (based on perltype COUNTER64)
 * The net-snmp type is ASN_COUNTER64. The C type decl is U64 (U64)
 */
/**
 * Extract the current value of the ifHCInMulticastPkts data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifHCInMulticastPkts_val_ptr
 *        Pointer to storage for a U64 variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifHCInMulticastPkts_get(ifXTable_rowreq_ctx * rowreq_ctx,
                        U64 * ifHCInMulticastPkts_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifHCInMulticastPkts_val_ptr);

    /*
     * TODO:231:o: |-> copy ifHCInMulticastPkts data.
     * get (* ifHCInMulticastPkts_val_ptr ).low and (* ifHCInMulticastPkts_val_ptr ).high from rowreq_ctx->data
     */
    (*ifHCInMulticastPkts_val_ptr).high =
        rowreq_ctx->data.ifHCInMulticastPkts.high;
    (*ifHCInMulticastPkts_val_ptr).low =
        rowreq_ctx->data.ifHCInMulticastPkts.low;


    return MFD_SUCCESS;
}                               /* ifHCInMulticastPkts_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifHCInBroadcastPkts
 * ifHCInBroadcastPkts is subid 9 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.9
 * Description:
The number of packets, delivered by this sub-layer to a
            higher (sub-)layer, which were addressed to a broadcast
            address at this sub-layer.  This object is a 64-bit version
            of ifInBroadcastPkts.

            Discontinuities in the value of this counter can occur at
            re-initialization of the management system, and at other
            times as indicated by the value of
            ifCounterDiscontinuityTime.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 *
 * Its syntax is COUNTER64 (based on perltype COUNTER64)
 * The net-snmp type is ASN_COUNTER64. The C type decl is U64 (U64)
 */
/**
 * Extract the current value of the ifHCInBroadcastPkts data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifHCInBroadcastPkts_val_ptr
 *        Pointer to storage for a U64 variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifHCInBroadcastPkts_get(ifXTable_rowreq_ctx * rowreq_ctx,
                        U64 * ifHCInBroadcastPkts_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifHCInBroadcastPkts_val_ptr);

    /*
     * TODO:231:o: |-> copy ifHCInBroadcastPkts data.
     * get (* ifHCInBroadcastPkts_val_ptr ).low and (* ifHCInBroadcastPkts_val_ptr ).high from rowreq_ctx->data
     */
    (*ifHCInBroadcastPkts_val_ptr).high =
        rowreq_ctx->data.ifHCInBroadcastPkts.high;
    (*ifHCInBroadcastPkts_val_ptr).low =
        rowreq_ctx->data.ifHCInBroadcastPkts.low;


    return MFD_SUCCESS;
}                               /* ifHCInBroadcastPkts_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifHCOutOctets
 * ifHCOutOctets is subid 10 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.10
 * Description:
The total number of octets transmitted out of the
            interface, including framing characters.  This object is a
            64-bit version of ifOutOctets.

            Discontinuities in the value of this counter can occur at
            re-initialization of the management system, and at other
            times as indicated by the value of
            ifCounterDiscontinuityTime.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 *
 * Its syntax is COUNTER64 (based on perltype COUNTER64)
 * The net-snmp type is ASN_COUNTER64. The C type decl is U64 (U64)
 */
/**
 * Extract the current value of the ifHCOutOctets data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifHCOutOctets_val_ptr
 *        Pointer to storage for a U64 variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifHCOutOctets_get(ifXTable_rowreq_ctx * rowreq_ctx,
                  U64 * ifHCOutOctets_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifHCOutOctets_val_ptr);

    /*
     * TODO:231:o: |-> copy ifHCOutOctets data.
     * get (* ifHCOutOctets_val_ptr ).low and (* ifHCOutOctets_val_ptr ).high from rowreq_ctx->data
     */
    (*ifHCOutOctets_val_ptr).high = rowreq_ctx->data.ifHCOutOctets.high;
    (*ifHCOutOctets_val_ptr).low = rowreq_ctx->data.ifHCOutOctets.low;


    return MFD_SUCCESS;
}                               /* ifHCOutOctets_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifHCOutUcastPkts
 * ifHCOutUcastPkts is subid 11 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.11
 * Description:
The total number of packets that higher-level protocols
            requested be transmitted, and which were not addressed to a
            multicast or broadcast address at this sub-layer, including
            those that were discarded or not sent.  This object is a
            64-bit version of ifOutUcastPkts.

            Discontinuities in the value of this counter can occur at
            re-initialization of the management system, and at other
            times as indicated by the value of
            ifCounterDiscontinuityTime.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 *
 * Its syntax is COUNTER64 (based on perltype COUNTER64)
 * The net-snmp type is ASN_COUNTER64. The C type decl is U64 (U64)
 */
/**
 * Extract the current value of the ifHCOutUcastPkts data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifHCOutUcastPkts_val_ptr
 *        Pointer to storage for a U64 variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifHCOutUcastPkts_get(ifXTable_rowreq_ctx * rowreq_ctx,
                     U64 * ifHCOutUcastPkts_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifHCOutUcastPkts_val_ptr);

    /*
     * TODO:231:o: |-> copy ifHCOutUcastPkts data.
     * get (* ifHCOutUcastPkts_val_ptr ).low and (* ifHCOutUcastPkts_val_ptr ).high from rowreq_ctx->data
     */
    (*ifHCOutUcastPkts_val_ptr).high =
        rowreq_ctx->data.ifHCOutUcastPkts.high;
    (*ifHCOutUcastPkts_val_ptr).low =
        rowreq_ctx->data.ifHCOutUcastPkts.low;


    return MFD_SUCCESS;
}                               /* ifHCOutUcastPkts_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifHCOutMulticastPkts
 * ifHCOutMulticastPkts is subid 12 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.12
 * Description:
The total number of packets that higher-level protocols
            requested be transmitted, and which were addressed to a
            multicast address at this sub-layer, including those that
            were discarded or not sent.  For a MAC layer protocol, this
            includes both Group and Functional addresses.  This object
            is a 64-bit version of ifOutMulticastPkts.

            Discontinuities in the value of this counter can occur at
            re-initialization of the management system, and at other
            times as indicated by the value of
            ifCounterDiscontinuityTime.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 *
 * Its syntax is COUNTER64 (based on perltype COUNTER64)
 * The net-snmp type is ASN_COUNTER64. The C type decl is U64 (U64)
 */
/**
 * Extract the current value of the ifHCOutMulticastPkts data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifHCOutMulticastPkts_val_ptr
 *        Pointer to storage for a U64 variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifHCOutMulticastPkts_get(ifXTable_rowreq_ctx * rowreq_ctx,
                         U64 * ifHCOutMulticastPkts_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifHCOutMulticastPkts_val_ptr);

    /*
     * TODO:231:o: |-> copy ifHCOutMulticastPkts data.
     * get (* ifHCOutMulticastPkts_val_ptr ).low and (* ifHCOutMulticastPkts_val_ptr ).high from rowreq_ctx->data
     */
    (*ifHCOutMulticastPkts_val_ptr).high =
        rowreq_ctx->data.ifHCOutMulticastPkts.high;
    (*ifHCOutMulticastPkts_val_ptr).low =
        rowreq_ctx->data.ifHCOutMulticastPkts.low;


    return MFD_SUCCESS;
}                               /* ifHCOutMulticastPkts_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifHCOutBroadcastPkts
 * ifHCOutBroadcastPkts is subid 13 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.13
 * Description:
The total number of packets that higher-level protocols
            requested be transmitted, and which were addressed to a
            broadcast address at this sub-layer, including those that
            were discarded or not sent.  This object is a 64-bit version
            of ifOutBroadcastPkts.

            Discontinuities in the value of this counter can occur at
            re-initialization of the management system, and at other
            times as indicated by the value of
            ifCounterDiscontinuityTime.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 *
 * Its syntax is COUNTER64 (based on perltype COUNTER64)
 * The net-snmp type is ASN_COUNTER64. The C type decl is U64 (U64)
 */
/**
 * Extract the current value of the ifHCOutBroadcastPkts data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifHCOutBroadcastPkts_val_ptr
 *        Pointer to storage for a U64 variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifHCOutBroadcastPkts_get(ifXTable_rowreq_ctx * rowreq_ctx,
                         U64 * ifHCOutBroadcastPkts_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifHCOutBroadcastPkts_val_ptr);

    /*
     * TODO:231:o: |-> copy ifHCOutBroadcastPkts data.
     * get (* ifHCOutBroadcastPkts_val_ptr ).low and (* ifHCOutBroadcastPkts_val_ptr ).high from rowreq_ctx->data
     */
    (*ifHCOutBroadcastPkts_val_ptr).high =
        rowreq_ctx->data.ifHCOutBroadcastPkts.high;
    (*ifHCOutBroadcastPkts_val_ptr).low =
        rowreq_ctx->data.ifHCOutBroadcastPkts.low;


    return MFD_SUCCESS;
}                               /* ifHCOutBroadcastPkts_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifLinkUpDownTrapEnable
 * ifLinkUpDownTrapEnable is subid 14 of ifXEntry.
 * Its status is Current, and its access level is ReadWrite.
 * OID: .1.3.6.1.2.1.31.1.1.1.14
 * Description:
Indicates whether linkUp/linkDown traps should be generated
            for this interface.

            By default, this object should have the value enabled(1) for
            interfaces which do not operate on 'top' of any other
            interface (as defined in the ifStackTable), and disabled(2)
            otherwise.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  1      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   1
 *
 * Enum range: 2/8. Values:  enabled(1), disabled(2)
 *
 * Its syntax is INTEGER (based on perltype INTEGER)
 * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
 */
/**
 * Extract the current value of the ifLinkUpDownTrapEnable data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifLinkUpDownTrapEnable_val_ptr
 *        Pointer to storage for a long variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifLinkUpDownTrapEnable_get(ifXTable_rowreq_ctx * rowreq_ctx,
                           u_long * ifLinkUpDownTrapEnable_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifLinkUpDownTrapEnable_val_ptr);


    DEBUGMSGTL(("verbose:ifXTable:ifLinkUpDownTrapEnable_get",
                "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:231:o: |-> Extract the current value of the ifLinkUpDownTrapEnable data.
     * set (* ifLinkUpDownTrapEnable_val_ptr ) from rowreq_ctx->data
     */
    (*ifLinkUpDownTrapEnable_val_ptr) =
        rowreq_ctx->data.ifLinkUpDownTrapEnable;

    return MFD_SUCCESS;
}                               /* ifLinkUpDownTrapEnable_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifHighSpeed
 * ifHighSpeed is subid 15 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.15
 * Description:
An estimate of the interface's current bandwidth in units
            of 1,000,000 bits per second.  If this object reports a
            value of `n' then the speed of the interface is somewhere in
            the range of `n-500,000' to `n+499,999'.  For interfaces
            which do not vary in bandwidth or for those where no
            accurate estimation can be made, this object should contain
            the nominal bandwidth.  For a sub-layer which has no concept
            of bandwidth, this object should be zero.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 *
 * Its syntax is GAUGE (based on perltype GAUGE)
 * The net-snmp type is ASN_GAUGE. The C type decl is u_long (u_long)
 */
/**
 * Extract the current value of the ifHighSpeed data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifHighSpeed_val_ptr
 *        Pointer to storage for a u_long variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifHighSpeed_get(ifXTable_rowreq_ctx * rowreq_ctx,
                u_long * ifHighSpeed_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifHighSpeed_val_ptr);


    DEBUGMSGTL(("verbose:ifXTable:ifHighSpeed_get", "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:231:o: |-> Extract the current value of the ifHighSpeed data.
     * set (* ifHighSpeed_val_ptr ) from rowreq_ctx->data
     */
    (*ifHighSpeed_val_ptr) = rowreq_ctx->data.ifHighSpeed;

    return MFD_SUCCESS;
}                               /* ifHighSpeed_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifPromiscuousMode
 * ifPromiscuousMode is subid 16 of ifXEntry.
 * Its status is Current, and its access level is ReadWrite.
 * OID: .1.3.6.1.2.1.31.1.1.1.16
 * Description:
This object has a value of false(2) if this interface only
            accepts packets/frames that are addressed to this station.
            This object has a value of true(1) when the station accepts
            all packets/frames transmitted on the media.  The value
            true(1) is only legal on certain types of media.  If legal,
            setting this object to a value of true(1) may require the
            interface to be reset before becoming effective.

            The value of ifPromiscuousMode does not affect the reception
            of broadcast and multicast packets/frames by the interface.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  1      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   1
 *
 * Enum range: 2/8. Values:  true(1), false(2)
 *
 * Its syntax is TruthValue (based on perltype INTEGER)
 * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
 */
/**
 * Extract the current value of the ifPromiscuousMode data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifPromiscuousMode_val_ptr
 *        Pointer to storage for a long variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifPromiscuousMode_get(ifXTable_rowreq_ctx * rowreq_ctx,
                      u_long * ifPromiscuousMode_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifPromiscuousMode_val_ptr);


    DEBUGMSGTL(("verbose:ifXTable:ifPromiscuousMode_get", "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:231:o: |-> Extract the current value of the ifPromiscuousMode data.
     * set (* ifPromiscuousMode_val_ptr ) from rowreq_ctx->data
     */
    (*ifPromiscuousMode_val_ptr) = rowreq_ctx->data.ifPromiscuousMode;

    return MFD_SUCCESS;
}                               /* ifPromiscuousMode_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifConnectorPresent
 * ifConnectorPresent is subid 17 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.17
 * Description:
This object has the value 'true(1)' if the interface
            sublayer has a physical connector and the value 'false(2)'
            otherwise.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  1      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 * Enum range: 2/8. Values:  true(1), false(2)
 *
 * Its syntax is TruthValue (based on perltype INTEGER)
 * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
 */
/**
 * Extract the current value of the ifConnectorPresent data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifConnectorPresent_val_ptr
 *        Pointer to storage for a long variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifConnectorPresent_get(ifXTable_rowreq_ctx * rowreq_ctx,
                       u_long * ifConnectorPresent_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifConnectorPresent_val_ptr);


    DEBUGMSGTL(("verbose:ifXTable:ifConnectorPresent_get", "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:231:o: |-> Extract the current value of the ifConnectorPresent data.
     * set (* ifConnectorPresent_val_ptr ) from rowreq_ctx->data
     */
    (*ifConnectorPresent_val_ptr) = rowreq_ctx->data.ifConnectorPresent;

    return MFD_SUCCESS;
}                               /* ifConnectorPresent_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifAlias
 * ifAlias is subid 18 of ifXEntry.
 * Its status is Current, and its access level is ReadWrite.
 * OID: .1.3.6.1.2.1.31.1.1.1.18
 * Description:
This object is an 'alias' name for the interface as
            specified by a network manager, and provides a non-volatile
            'handle' for the interface.

            On the first instantiation of an interface, the value of
            ifAlias associated with that interface is the zero-length
            string.  As and when a value is written into an instance of
            ifAlias through a network management set operation, then the
            agent must retain the supplied value in the ifAlias instance
            associated with the same interface for as long as that
            interface remains instantiated, including across all re-
            initializations/reboots of the network management system,
            including those which result in a change of the interface's
            ifIndex value.

            An example of the value which a network manager might store
            in this object for a WAN interface is the (Telco's) circuit
            number/identifier of the interface.

            Some agents may support write-access only for interfaces
            having particular values of ifType.  An agent which supports
            write access to this object is required to keep the value in
            non-volatile storage, but it may limit the length of new
            values depending on how much storage is already occupied by
            the current values for other interfaces.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 1      hashint   1
 *   settable   1
 *   hint: 255a
 *
 * Ranges:  0 - 64;
 *
 * Its syntax is DisplayString (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 64)
 */
/**
 * Extract the current value of the ifAlias data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifAlias_val_ptr_ptr
 *        Pointer to storage for a char variable
 * @param ifAlias_val_ptr_len_ptr
 *        Pointer to a size_t. On entry, it will contain the size (in bytes)
 *        pointed to by ifAlias.
 *        On exit, this value should contain the data size (in bytes).
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
*
 * @note If you need more than (*ifAlias_val_ptr_len_ptr) bytes of memory,
 *       allocate it using malloc() and update ifAlias_val_ptr_ptr.
 *       <b>DO NOT</b> free the previous pointer.
 *       The MFD helper will release the memory you allocate.
 *
 * @remark If you call this function yourself, you are responsible
 *         for checking if the pointer changed, and freeing any
 *         previously allocated memory. (Not necessary if you pass
 *         in a pointer to static memory, obviously.)
 */
int
ifAlias_get(ifXTable_rowreq_ctx * rowreq_ctx, char **ifAlias_val_ptr_ptr,
            size_t *ifAlias_val_ptr_len_ptr)
{
   /** we should have a non-NULL pointer and enough storage */
    netsnmp_assert((NULL != ifAlias_val_ptr_ptr)
                   && (NULL != *ifAlias_val_ptr_ptr));
    netsnmp_assert(NULL != ifAlias_val_ptr_len_ptr);


    DEBUGMSGTL(("verbose:ifXTable:ifAlias_get", "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:231:o: |-> Extract the current value of the ifAlias data.
     * set (* ifAlias_val_ptr_ptr ) and (* ifAlias_val_ptr_len_ptr ) from rowreq_ctx->data
     */
    /*
     * make sure there is enough space for ifAlias data
     */
    if ((NULL == (*ifAlias_val_ptr_ptr))
        || ((*ifAlias_val_ptr_len_ptr) < rowreq_ctx->data.ifAlias_len)) {
        /*
         * allocate space for ifAlias data
         */
        (*ifAlias_val_ptr_ptr) =
            malloc(rowreq_ctx->data.ifAlias_len *
                   sizeof((*ifAlias_val_ptr_ptr)[0]));
        if (NULL == (*ifAlias_val_ptr_ptr)) {
            snmp_log(LOG_ERR, "could not allocate memory\n");
            return MFD_ERROR;
        }
    }
    (*ifAlias_val_ptr_len_ptr) = rowreq_ctx->data.ifAlias_len;
    memcpy((*ifAlias_val_ptr_ptr), rowreq_ctx->data.ifAlias,
           (*ifAlias_val_ptr_len_ptr) * sizeof((*ifAlias_val_ptr_ptr)[0]));

    return MFD_SUCCESS;
}                               /* ifAlias_get */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifCounterDiscontinuityTime
 * ifCounterDiscontinuityTime is subid 19 of ifXEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.31.1.1.1.19
 * Description:
The value of sysUpTime on the most recent occasion at which
            any one or more of this interface's counters suffered a
            discontinuity.  The relevant counters are the specific
            instances associated with this interface of any Counter32 or

            Counter64 object contained in the ifTable or ifXTable.  If
            no such discontinuities have occurred since the last re-
            initialization of the local management subsystem, then this
            object contains a zero value.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   0
 *
 *
 * Its syntax is TimeStamp (based on perltype TICKS)
 * The net-snmp type is ASN_TIMETICKS. The C type decl is u_long (u_long)
 */
/**
 * Extract the current value of the ifCounterDiscontinuityTime data.
 *
 * Set a value using the data context for the row.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifCounterDiscontinuityTime_val_ptr
 *        Pointer to storage for a u_long variable
 *
 * @retval MFD_SUCCESS         : success
 * @retval MFD_SKIP            : skip this node (no value for now)
 * @retval MFD_ERROR           : Any other error
 */
int
ifCounterDiscontinuityTime_get(ifXTable_rowreq_ctx * rowreq_ctx,
                               u_long * ifCounterDiscontinuityTime_val_ptr)
{
   /** we should have a non-NULL pointer */
    netsnmp_assert(NULL != ifCounterDiscontinuityTime_val_ptr);


    DEBUGMSGTL(("verbose:ifXTable:ifCounterDiscontinuityTime_get",
                "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:231:o: |-> Extract the current value of the ifCounterDiscontinuityTime data.
     * set (* ifCounterDiscontinuityTime_val_ptr ) from rowreq_ctx->data
     */
    (*ifCounterDiscontinuityTime_val_ptr) =
        rowreq_ctx->data.ifCounterDiscontinuityTime;

    return MFD_SUCCESS;
}                               /* ifCounterDiscontinuityTime_get */



/** @} */
/**********************************************************************
 **********************************************************************
 ***
 *** Table ifXTable
 ***
 **********************************************************************
 **********************************************************************/
/*
 * ifXTable is subid 1 of ifMIBObjects.
 * Its status is Current.
 * OID: .1.3.6.1.2.1.31.1.1, length: 9
 */
    /*
     * NOTE: if you update this chart, please update the versions in
     *       local/mib2c-conf.d/parent-set.m2i
     *       agent/mibgroup/helpers/baby_steps.c
     * while you're at it.
     */
    /*
     ***********************************************************************
     * Baby Steps Flow Chart (2004.06.05)                                  *
     *                                                                     *
     * +--------------+    +================+    U = unconditional path    *
     * |optional state|    ||required state||    S = path for success      *
     * +--------------+    +================+    E = path for error        *
     ***********************************************************************
     *
     *                        +--------------+
     *                        |     pre      |
     *                        |   request    |
     *                        +--------------+
     *                               | U
     *                        +==============+
     *       +----------------||  object    ||
     *       |              E ||  lookup    ||
     *       |                +==============+
     *       |                       | S
     *       |                +==============+
     *       |              E ||   check    ||
     *       |<---------------||   values   ||
     *       |                +==============+
     *       |                       | S
     *       |                +==============+
     *       |       +<-------||   undo     ||
     *       |       |      E ||   setup    ||
     *       |       |        +==============+
     *       |       |               | S
     *       |       |        +==============+
     *       |       |        ||    set     ||-------------------------->+
     *       |       |        ||   value    || E                         |
     *       |       |        +==============+                           |
     *       |       |               | S                                 |
     *       |       |        +--------------+                           |
     *       |       |        |    check     |-------------------------->|
     *       |       |        |  consistency | E                         |
     *       |       |        +--------------+                           |
     *       |       |               | S                                 |
     *       |       |        +==============+         +==============+  |
     *       |       |        ||   commit   ||-------->||     undo   ||  |
     *       |       |        ||            || E       ||    commit  ||  |
     *       |       |        +==============+         +==============+  |
     *       |       |               | S                     U |<--------+
     *       |       |        +--------------+         +==============+
     *       |       |        | irreversible |         ||    undo    ||
     *       |       |        |    commit    |         ||     set    ||
     *       |       |        +--------------+         +==============+
     *       |       |               | U                     U |
     *       |       +-------------->|<------------------------+
     *       |                +==============+
     *       |                ||   undo     ||
     *       |                ||  cleanup   ||
     *       |                +==============+
     *       +---------------------->| U
     *                        +--------------+
     *                        |    post      |
     *                        |   request    |
     *                        +--------------+
     *
     */

/**
 * Setup up context with information needed to undo a set request.
 *
 * This function will be called before the individual node undo setup
 * functions are called. If you need to do any undo setup that is not
 * related to a specific column, you can do it here.
 *
 * Note that the undo context has been allocated with
 * ifXTable_allocate_data(), but may need extra
 * initialization similar to what you may have done in
 * ifXTable_rowreq_ctx_init().
 * Note that an individual node's undo_setup function will only be called
 * if that node is being set to a new value.
 *
 * If there is any setup specific to a particular column (e.g. allocating
 * memory for a string), you should do that setup in the node's undo_setup
 * function, so it won't be done unless it is necessary.
 *
 * @param rowreq_ctx
 *        Pointer to the table context (ifXTable_rowreq_ctx)
 *
 * @retval MFD_SUCCESS : success
 * @retval MFD_ERROR   : error. set will fail.
 */
int
ifXTable_undo_setup(ifXTable_rowreq_ctx * rowreq_ctx)
{
    int             rc = MFD_SUCCESS;

    DEBUGMSGTL(("verbose:ifXTable:ifXTable_undo_setup", "called\n"));

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

    /*
     * TODO:451:M: |-> Setup ifXTable undo.
     * set up ifXTable undo information, in preparation for a set.
     */

    return rc;
}                               /* ifXTable_undo_setup */

/**
 * Cleanup up context undo information.
 *
 * This function will be called after set/commit processing. If you
 * allocated any resources in undo_setup, this is the place to release
 * those resources.
 *
 * This function is called regardless of the success or failure of the set
 * request. If you need to perform different steps for cleanup depending
 * on success or failure, you can add a flag to the rowreq_ctx.
 *
 * @param rowreq_ctx
 *        Pointer to the table context (ifXTable_rowreq_ctx)
 *
 * @retval MFD_SUCCESS : success
 * @retval MFD_ERROR   : error
 */
int
ifXTable_undo_cleanup(ifXTable_rowreq_ctx * rowreq_ctx)
{
    int             rc = MFD_SUCCESS;

    DEBUGMSGTL(("verbose:ifXTable:ifXTable_undo_cleanup", "called\n"));

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

    /*
     * TODO:452:M: |-> Cleanup ifXTable undo.
     */

    return rc;
}                               /* ifXTable_undo_cleanup */

/**
 * commit new values.
 *
 * At this point, you should have done everything you can to ensure that
 * this commit will not fail.
 *
 * Should you need different behavior depending on which columns were
 * set, rowreq_ctx->column_set_flags will indicate which writeable columns were
 * set. The definitions for the FLAG_* bits can be found in
 * ifXTable.h.
 * A new row will have the MFD_ROW_CREATED bit set in rowreq_flags.
 *
 * @param ifXTable_rowreq_ctx
 *        Pointer to the users context.
 *
 * @retval MFD_SUCCESS : success
 * @retval MFD_ERROR   : error
 */
int
ifXTable_commit(ifXTable_rowreq_ctx * rowreq_ctx)
{
    int             rc = MFD_SUCCESS;
    int             save_flags;

    DEBUGMSGTL(("verbose:ifXTable:ifXTable_commit", "called\n"));

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

    /*
     * save flags, then clear until we actually do something
     */
    save_flags = rowreq_ctx->column_set_flags;
    rowreq_ctx->column_set_flags = 0;

    /*
     * commit ifXTable data
     * 1) check the column's flag in save_flags to see if it was set.
     * 2) clear the flag when you handle that column
     * 3) set the column's flag in column_set_flags if it needs undo
     *    processing in case of a failure.
     *
     * this is where one would usually commit data. In this case,
     * ifLinkUpDownTrapEnable and ifAlias are purely internal, so
     * nothing needs to be done. That leaves ifPromiscuosMode,
     * which I'm leery about implementing. Thus, at this point,
     * there is nothing to do except twiddle flag bits.
     *
     * in keeping with the net-snmp persistence policy, changes are kept
     * in memory, and saved to disk when the agent shuts down.
     */
    if (save_flags & FLAG_IFLINKUPDOWNTRAPENABLE) {
        save_flags &= ~FLAG_IFLINKUPDOWNTRAPENABLE;     /* clear ifLinkUpDownTrapEnable */
        /*
         * TODO:482:o: |-> commit column ifLinkUpDownTrapEnable.
         */
        /*
         * set flag, in case we need to undo ifLinkUpDownTrapEnable
         */
        rowreq_ctx->column_set_flags |= FLAG_IFLINKUPDOWNTRAPENABLE;
    }

    if (save_flags & FLAG_IFPROMISCUOUSMODE) {
        save_flags &= ~FLAG_IFPROMISCUOUSMODE;  /* clear ifPromiscuousMode */
#ifdef NETSNMP_ENABLE_PROMISCUOUSMODE_SET
        /*
         * TODO:482:o: |-> commit column ifPromiscuousMode.
         */
        rc = -1;
        if (-1 == rc) {
            snmp_log(LOG_ERR,
                     "ifXTable column ifPromiscuousMode commit failed\n");
        } else {
            /*
             * set flag, in case we need to undo ifPromiscuousMode
             */
            rowreq_ctx->column_set_flags |= FLAG_IFPROMISCUOUSMODE;
        }
#endif
    }

    if (save_flags & FLAG_IFALIAS) {
        save_flags &= ~FLAG_IFALIAS;    /* clear ifAlias */
        /*
         * TODO:482:o: |-> commit column ifAlias.
         */
        /*
         * set flag, in case we need to undo ifAlias
         */
        rowreq_ctx->column_set_flags |= FLAG_IFALIAS;
    }

    if (save_flags) {
        snmp_log(LOG_ERR, "unhandled columns (0x%x) in commit\n",
                 save_flags);
        return MFD_ERROR;
    }

    return rc;
}                               /* ifXTable_commit */

/**
 * undo commit new values.
 *
 * Should you need different behavior depending on which columns were
 * set, rowreq_ctx->column_set_flags will indicate which writeable columns were
 * set. The definitions for the FLAG_* bits can be found in
 * ifXTable.h.
 * A new row will have the MFD_ROW_CREATED bit set in rowreq_flags.
 *
 * @param ifXTable_rowreq_ctx
 *        Pointer to the users context.
 *
 * @retval MFD_SUCCESS : success
 * @retval MFD_ERROR   : error
 */
int
ifXTable_undo_commit(ifXTable_rowreq_ctx * rowreq_ctx)
{
    int             rc = MFD_SUCCESS;

    DEBUGMSGTL(("verbose:ifXTable:ifXTable_undo_commit", "called\n"));

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

    /*
     * TODO:485:M: |-> Undo ifXTable commit.
     * check the column's flag in rowreq_ctx->column_set_flags to see
     * if it was set during commit, then undo it.
     *
     * eg: if (rowreq_ctx->column_set_flags & FLAG_) {}
     */

    return rc;
}                               /* ifXTable_undo_commit */

/*
 * TODO:420:r: Implement ifXTable index validation.
 */
/*---------------------------------------------------------------------
 * IF-MIB::ifEntry.ifIndex
 * ifIndex is subid 1 of ifEntry.
 * Its status is Current, and its access level is ReadOnly.
 * OID: .1.3.6.1.2.1.2.2.1.1
 * Description:
A unique value, greater than zero, for each interface.  It
            is recommended that values are assigned contiguously
            starting from 1.  The value for each interface sub-layer
            must remain constant at least from one re-initialization of
            the entity's network management system to the next re-
            initialization.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     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)
 */
/*
 * TODO:440:M: Implement ifXTable node value checks.
 * TODO:450:M: Implement ifXTable undo functions.
 * TODO:460:M: Implement ifXTable set functions.
 * TODO:480:M: Implement ifXTable commit functions.
 */
/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifLinkUpDownTrapEnable
 * ifLinkUpDownTrapEnable is subid 14 of ifXEntry.
 * Its status is Current, and its access level is ReadWrite.
 * OID: .1.3.6.1.2.1.31.1.1.1.14
 * Description:
Indicates whether linkUp/linkDown traps should be generated
            for this interface.

            By default, this object should have the value enabled(1) for
            interfaces which do not operate on 'top' of any other
            interface (as defined in the ifStackTable), and disabled(2)
            otherwise.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  1      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   1
 *
 * Enum range: 2/8. Values:  enabled(1), disabled(2)
 *
 * Its syntax is INTEGER (based on perltype INTEGER)
 * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
 */
/**
 * Check that the proposed new value is potentially valid.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifLinkUpDownTrapEnable_val
 *        A long containing the new value.
 *
 * @retval MFD_SUCCESS        : incoming value is legal
 * @retval MFD_NOT_VALID_NOW  : incoming value is not valid now
 * @retval MFD_NOT_VALID_EVER : incoming value is never valid
 *
 * This is the place to check for requirements that are not
 * expressed in the mib syntax (for example, a requirement that
 * is detailed in the description for an object).
 *
 * You should check that the requested change between the undo value and the
 * new value is legal (ie, the transistion from one value to another
 * is legal).
 *      
 *@note
 * This check is only to determine if the new value
 * is \b potentially valid. This is the first check of many, and
 * is one of the simplest ones.
 * 
 *@note
 * this is not the place to do any checks for values
 * which depend on some other value in the mib. Those
 * types of checks should be done in the
 * ifXTable_check_dependencies() function.
 *
 * The following checks have already been done for you:
 *    The syntax is ASN_INTEGER
 *    The value is one of  enabled(1), disabled(2)
 *
 * If there a no other checks you need to do, simply return MFD_SUCCESS.
 *
 */
int
ifLinkUpDownTrapEnable_check_value(ifXTable_rowreq_ctx * rowreq_ctx,
                                   u_long ifLinkUpDownTrapEnable_val)
{
    DEBUGMSGTL(("verbose:ifXTable:ifLinkUpDownTrapEnable_check_value",
                "called\n"));

    /** should never get a NULL pointer */
    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:441:o: |-> Check for valid ifLinkUpDownTrapEnable value.
     */

    return MFD_SUCCESS;         /* ifLinkUpDownTrapEnable value not illegal */
}                               /* ifLinkUpDownTrapEnable_check_value */

/**
 * Save old value information
 *
 * @param rowreq_ctx
 *        Pointer to the table context (ifXTable_rowreq_ctx)
 *
 * @retval MFD_SUCCESS : success
 * @retval MFD_ERROR   : error. set will fail.
 *
 * This function will be called after the table level undo setup function
 * ifXTable_undo_setup has been called.
 *
 *@note
 * this function will only be called if a new value is set for this column.
 *
 * If there is any setup specific to a particular column (e.g. allocating
 * memory for a string), you should do that setup in this function, so it
 * won't be done unless it is necessary.
 */
int
ifLinkUpDownTrapEnable_undo_setup(ifXTable_rowreq_ctx * rowreq_ctx)
{
    DEBUGMSGTL(("verbose:ifXTable:ifLinkUpDownTrapEnable_undo_setup",
                "called\n"));

    /** should never get a NULL pointer */
    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:455:o: |-> Setup ifLinkUpDownTrapEnable undo.
     */
    /*
     * copy ifLinkUpDownTrapEnable data
     * set rowreq_ctx->undo->ifLinkUpDownTrapEnable from rowreq_ctx->data.ifLinkUpDownTrapEnable
     */
    rowreq_ctx->undo->ifLinkUpDownTrapEnable =
        rowreq_ctx->data.ifLinkUpDownTrapEnable;


    return MFD_SUCCESS;
}                               /* ifLinkUpDownTrapEnable_undo_setup */

/**
 * Set the new value.
 *
 * @param rowreq_ctx
 *        Pointer to the users context. You should know how to
 *        manipulate the value from this object.
 * @param ifLinkUpDownTrapEnable_val
 *        A long containing the new value.
 */
int
ifLinkUpDownTrapEnable_set(ifXTable_rowreq_ctx * rowreq_ctx,
                           u_long ifLinkUpDownTrapEnable_val)
{

    DEBUGMSGTL(("verbose:ifXTable:ifLinkUpDownTrapEnable_set",
                "called\n"));

    /** should never get a NULL pointer */
    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:461:M: |-> Set ifLinkUpDownTrapEnable value.
     * set ifLinkUpDownTrapEnable value in rowreq_ctx->data
     */
    rowreq_ctx->data.ifLinkUpDownTrapEnable = ifLinkUpDownTrapEnable_val;

    return MFD_SUCCESS;
}                               /* ifLinkUpDownTrapEnable_set */

/**
 * undo the previous set.
 *
 * @param rowreq_ctx
 *        Pointer to the users context.
 */
int
ifLinkUpDownTrapEnable_undo(ifXTable_rowreq_ctx * rowreq_ctx)
{

    DEBUGMSGTL(("verbose:ifXTable:ifLinkUpDownTrapEnable_undo",
                "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:456:o: |-> Clean up ifLinkUpDownTrapEnable undo.
     */
    /*
     * copy ifLinkUpDownTrapEnable data
     * set rowreq_ctx->data.ifLinkUpDownTrapEnable from rowreq_ctx->undo->ifLinkUpDownTrapEnable
     */
    rowreq_ctx->data.ifLinkUpDownTrapEnable =
        rowreq_ctx->undo->ifLinkUpDownTrapEnable;


    return MFD_SUCCESS;
}                               /* ifLinkUpDownTrapEnable_undo */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifPromiscuousMode
 * ifPromiscuousMode is subid 16 of ifXEntry.
 * Its status is Current, and its access level is ReadWrite.
 * OID: .1.3.6.1.2.1.31.1.1.1.16
 * Description:
This object has a value of false(2) if this interface only
            accepts packets/frames that are addressed to this station.
            This object has a value of true(1) when the station accepts
            all packets/frames transmitted on the media.  The value
            true(1) is only legal on certain types of media.  If legal,
            setting this object to a value of true(1) may require the
            interface to be reset before becoming effective.

            The value of ifPromiscuousMode does not affect the reception
            of broadcast and multicast packets/frames by the interface.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  1      hasdefval 0
 *   readable   1     iscolumn 1     ranges 0      hashint   0
 *   settable   1
 *
 * Enum range: 2/8. Values:  true(1), false(2)
 *
 * Its syntax is TruthValue (based on perltype INTEGER)
 * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long)
 */
/**
 * Check that the proposed new value is potentially valid.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifPromiscuousMode_val
 *        A long containing the new value.
 *
 * @retval MFD_SUCCESS        : incoming value is legal
 * @retval MFD_NOT_VALID_NOW  : incoming value is not valid now
 * @retval MFD_NOT_VALID_EVER : incoming value is never valid
 *
 * This is the place to check for requirements that are not
 * expressed in the mib syntax (for example, a requirement that
 * is detailed in the description for an object).
 *
 * You should check that the requested change between the undo value and the
 * new value is legal (ie, the transistion from one value to another
 * is legal).
 *      
 *@note
 * This check is only to determine if the new value
 * is \b potentially valid. This is the first check of many, and
 * is one of the simplest ones.
 * 
 *@note
 * this is not the place to do any checks for values
 * which depend on some other value in the mib. Those
 * types of checks should be done in the
 * ifXTable_check_dependencies() function.
 *
 * The following checks have already been done for you:
 *    The syntax is ASN_INTEGER
 *    The value is one of  true(1), false(2)
 *
 * If there a no other checks you need to do, simply return MFD_SUCCESS.
 *
 */
int
ifPromiscuousMode_check_value(ifXTable_rowreq_ctx * rowreq_ctx,
                              u_long ifPromiscuousMode_val)
{
    DEBUGMSGTL(("verbose:ifXTable:ifPromiscuousMode_check_value",
                "called\n"));

    /** should never get a NULL pointer */
    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:441:o: |-> Check for valid ifPromiscuousMode value.
     */

    return MFD_SUCCESS;         /* ifPromiscuousMode value not illegal */
}                               /* ifPromiscuousMode_check_value */

/**
 * Save old value information
 *
 * @param rowreq_ctx
 *        Pointer to the table context (ifXTable_rowreq_ctx)
 *
 * @retval MFD_SUCCESS : success
 * @retval MFD_ERROR   : error. set will fail.
 *
 * This function will be called after the table level undo setup function
 * ifXTable_undo_setup has been called.
 *
 *@note
 * this function will only be called if a new value is set for this column.
 *
 * If there is any setup specific to a particular column (e.g. allocating
 * memory for a string), you should do that setup in this function, so it
 * won't be done unless it is necessary.
 */
int
ifPromiscuousMode_undo_setup(ifXTable_rowreq_ctx * rowreq_ctx)
{
    DEBUGMSGTL(("verbose:ifXTable:ifPromiscuousMode_undo_setup",
                "called\n"));

    /** should never get a NULL pointer */
    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:455:o: |-> Setup ifPromiscuousMode undo.
     */
    /*
     * copy ifPromiscuousMode data
     * set rowreq_ctx->undo->ifPromiscuousMode from rowreq_ctx->data.ifPromiscuousMode
     */
    rowreq_ctx->undo->ifPromiscuousMode =
        rowreq_ctx->data.ifPromiscuousMode;


#ifdef NETSNMP_ENABLE_PROMISCUOUSMODE_SET
    return MFD_SUCCESS;
#else
    return MFD_NOT_VALID_EVER;
#endif
}                               /* ifPromiscuousMode_undo_setup */

/**
 * Set the new value.
 *
 * @param rowreq_ctx
 *        Pointer to the users context. You should know how to
 *        manipulate the value from this object.
 * @param ifPromiscuousMode_val
 *        A long containing the new value.
 */
int
ifPromiscuousMode_set(ifXTable_rowreq_ctx * rowreq_ctx,
                      u_long ifPromiscuousMode_val)
{

    DEBUGMSGTL(("verbose:ifXTable:ifPromiscuousMode_set", "called\n"));

    /** should never get a NULL pointer */
    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:461:M: |-> Set ifPromiscuousMode value.
     * set ifPromiscuousMode value in rowreq_ctx->data
     */
    rowreq_ctx->data.ifPromiscuousMode = ifPromiscuousMode_val;

    return MFD_SUCCESS;
}                               /* ifPromiscuousMode_set */

/**
 * undo the previous set.
 *
 * @param rowreq_ctx
 *        Pointer to the users context.
 */
int
ifPromiscuousMode_undo(ifXTable_rowreq_ctx * rowreq_ctx)
{

    DEBUGMSGTL(("verbose:ifXTable:ifPromiscuousMode_undo", "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:456:o: |-> Clean up ifPromiscuousMode undo.
     */
    /*
     * copy ifPromiscuousMode data
     * set rowreq_ctx->data.ifPromiscuousMode from rowreq_ctx->undo->ifPromiscuousMode
     */
    rowreq_ctx->data.ifPromiscuousMode =
        rowreq_ctx->undo->ifPromiscuousMode;


    return MFD_SUCCESS;
}                               /* ifPromiscuousMode_undo */

/*---------------------------------------------------------------------
 * IF-MIB::ifXEntry.ifAlias
 * ifAlias is subid 18 of ifXEntry.
 * Its status is Current, and its access level is ReadWrite.
 * OID: .1.3.6.1.2.1.31.1.1.1.18
 * Description:
This object is an 'alias' name for the interface as
            specified by a network manager, and provides a non-volatile
            'handle' for the interface.

            On the first instantiation of an interface, the value of
            ifAlias associated with that interface is the zero-length
            string.  As and when a value is written into an instance of
            ifAlias through a network management set operation, then the
            agent must retain the supplied value in the ifAlias instance
            associated with the same interface for as long as that
            interface remains instantiated, including across all re-
            initializations/reboots of the network management system,
            including those which result in a change of the interface's
            ifIndex value.

            An example of the value which a network manager might store
            in this object for a WAN interface is the (Telco's) circuit
            number/identifier of the interface.

            Some agents may support write-access only for interfaces
            having particular values of ifType.  An agent which supports
            write access to this object is required to keep the value in
            non-volatile storage, but it may limit the length of new
            values depending on how much storage is already occupied by
            the current values for other interfaces.
 *
 * Attributes:
 *   accessible 1     isscalar 0     enums  0      hasdefval 0
 *   readable   1     iscolumn 1     ranges 1      hashint   1
 *   settable   1
 *   hint: 255a
 *
 * Ranges:  0 - 64;
 *
 * Its syntax is DisplayString (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 64)
 */
/**
 * Check that the proposed new value is potentially valid.
 *
 * @param rowreq_ctx
 *        Pointer to the row request context.
 * @param ifAlias_val_ptr
 *        A char containing the new value.
 * @param ifAlias_val_ptr_len
 *        The size (in bytes) of the data pointed to by ifAlias_val_ptr
 *
 * @retval MFD_SUCCESS        : incoming value is legal
 * @retval MFD_NOT_VALID_NOW  : incoming value is not valid now
 * @retval MFD_NOT_VALID_EVER : incoming value is never valid
 *
 * This is the place to check for requirements that are not
 * expressed in the mib syntax (for example, a requirement that
 * is detailed in the description for an object).
 *
 * You should check that the requested change between the undo value and the
 * new value is legal (ie, the transistion from one value to another
 * is legal).
 *      
 *@note
 * This check is only to determine if the new value
 * is \b potentially valid. This is the first check of many, and
 * is one of the simplest ones.
 * 
 *@note
 * this is not the place to do any checks for values
 * which depend on some other value in the mib. Those
 * types of checks should be done in the
 * ifXTable_check_dependencies() function.
 *
 * The following checks have already been done for you:
 *    The syntax is ASN_OCTET_STR
 *    The length is in (one of) the range set(s):  0 - 64
 *
 * If there a no other checks you need to do, simply return MFD_SUCCESS.
 *
 */
int
ifAlias_check_value(ifXTable_rowreq_ctx * rowreq_ctx,
                    char *ifAlias_val_ptr, size_t ifAlias_val_ptr_len)
{
    DEBUGMSGTL(("verbose:ifXTable:ifAlias_check_value", "called\n"));

    /** should never get a NULL pointer */
    netsnmp_assert(NULL != rowreq_ctx);
    netsnmp_assert(NULL != ifAlias_val_ptr);

    /*
     * TODO:441:o: |-> Check for valid ifAlias value.
     */

    return MFD_SUCCESS;         /* ifAlias value not illegal */
}                               /* ifAlias_check_value */

/**
 * Save old value information
 *
 * @param rowreq_ctx
 *        Pointer to the table context (ifXTable_rowreq_ctx)
 *
 * @retval MFD_SUCCESS : success
 * @retval MFD_ERROR   : error. set will fail.
 *
 * This function will be called after the table level undo setup function
 * ifXTable_undo_setup has been called.
 *
 *@note
 * this function will only be called if a new value is set for this column.
 *
 * If there is any setup specific to a particular column (e.g. allocating
 * memory for a string), you should do that setup in this function, so it
 * won't be done unless it is necessary.
 */
int
ifAlias_undo_setup(ifXTable_rowreq_ctx * rowreq_ctx)
{
    DEBUGMSGTL(("verbose:ifXTable:ifAlias_undo_setup", "called\n"));

    /** should never get a NULL pointer */
    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:455:o: |-> Setup ifAlias undo.
     */
    /*
     * copy ifAlias and ifAlias_len data
     * set rowreq_ctx->undo->ifAlias from rowreq_ctx->data.ifAlias
     */
    memcpy(rowreq_ctx->undo->ifAlias, rowreq_ctx->data.ifAlias,
           (rowreq_ctx->data.ifAlias_len *
            sizeof(rowreq_ctx->undo->ifAlias[0])));
    rowreq_ctx->undo->ifAlias_len = rowreq_ctx->data.ifAlias_len;


    return MFD_SUCCESS;
}                               /* ifAlias_undo_setup */

/**
 * Set the new value.
 *
 * @param rowreq_ctx
 *        Pointer to the users context. You should know how to
 *        manipulate the value from this object.
 * @param ifAlias_val_ptr
 *        A char containing the new value.
 * @param ifAlias_val_ptr_len
 *        The size (in bytes) of the data pointed to by ifAlias_val_ptr
 */
int
ifAlias_set(ifXTable_rowreq_ctx * rowreq_ctx, char *ifAlias_val_ptr,
            size_t ifAlias_val_ptr_len)
{

    DEBUGMSGTL(("verbose:ifXTable:ifAlias_set", "called\n"));

    /** should never get a NULL pointer */
    netsnmp_assert(NULL != rowreq_ctx);
    netsnmp_assert(NULL != ifAlias_val_ptr);

    /*
     * TODO:461:M: |-> Set ifAlias value.
     * set ifAlias value in rowreq_ctx->data
     */
    memcpy(rowreq_ctx->data.ifAlias, ifAlias_val_ptr,
           ifAlias_val_ptr_len * sizeof(ifAlias_val_ptr[0]));
    rowreq_ctx->data.ifAlias_len = ifAlias_val_ptr_len;

    return MFD_SUCCESS;
}                               /* ifAlias_set */

/**
 * undo the previous set.
 *
 * @param rowreq_ctx
 *        Pointer to the users context.
 */
int
ifAlias_undo(ifXTable_rowreq_ctx * rowreq_ctx)
{

    DEBUGMSGTL(("verbose:ifXTable:ifAlias_undo", "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:456:o: |-> Clean up ifAlias undo.
     */
    /*
     * copy ifAlias and ifAlias_len data
     * set rowreq_ctx->data.ifAlias from rowreq_ctx->undo->ifAlias
     */
    memcpy(rowreq_ctx->data.ifAlias, rowreq_ctx->undo->ifAlias,
           (rowreq_ctx->undo->ifAlias_len *
            sizeof(rowreq_ctx->data.ifAlias[0])));
    rowreq_ctx->data.ifAlias_len = rowreq_ctx->undo->ifAlias_len;


    return MFD_SUCCESS;
}                               /* ifAlias_undo */

/**
 * check dependencies
 *
 * This is useful for for tables which have dependencies between columns
 * (or rows, or tables). For example, two columns allocating a percentage
 * of something add up 100%.
 *
 * Should you need different behavior depending on which columns were
 * set, rowreq_ctx->column_set_flags will indicate which writeable columns were
 * set. The definitions for the FLAG_* bits can be found in
 * ifXTable.h.
 * A new row will have the MFD_ROW_CREATED bit set in rowreq_flags.
 *
 * @retval MFD_SUCCESS all the changes to the row are legal
 * @retval MFD_ERROR   one or more changes are not legal
 *
 * (see README-table-ifXTable if you don't have dependencies)
 */
int
ifXTable_check_dependencies(ifXTable_rowreq_ctx * rowreq_ctx)
{
    int             rc = MFD_SUCCESS;

    DEBUGMSGTL(("internal:ifXTable:ifXTable_check_dependencies",
                "called\n"));

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * TODO:470:o: Check ifXTable row dependencies.
     * check that all new value are legal and consistent with each other
     */
    return rc;
}                               /* ifXTable_check_dependencies */

/** @} */
/** @{ */

int
_ifXTable_row_save(ifXTable_rowreq_ctx * rowreq_ctx, void *type)
{
    char           *buf, *line;
    int             size;

    netsnmp_assert(NULL != rowreq_ctx);

    /*
     * allocate space for data. Remeber, data will be stored in
     * ASCII form, so you need to allow for that. Here are some
     * general guidelines:
     *
     * Object ID :  12 * len (ASCII len of max int + 1 for .)
     * Octet String: (2 * len) + 2 (2 ASCII chars per byte + "0x")
     * Integers :  12 (ASCII len for smallest negative number)
     */
    size = sizeof(row_token) + 1 +      /* 'ifXTable ' */
        13 +                    /* ifIndex value + ' ' */
        13 +                    /* col #, + ':' */
        rowreq_ctx->data.ifAlias_len + 2 +      /* [0|1] + ' ' */
        4;                      /* '\n\0' & possible quoting */

    /*
     * allocate memory for the line
     */
    line = buf = calloc(1, size);
    if (NULL == buf) {
        snmp_log(LOG_ERR, "error allocating memory while saving row\n");
        return SNMP_ERR_GENERR;
    }

    /*
     * build the line
     */
    buf += sprintf(buf, "%s ", row_token);
    buf = read_config_save_objid(buf, rowreq_ctx->oid_idx.oids,
                                 rowreq_ctx->oid_idx.len);
    if (NULL == buf) {
        snmp_log(LOG_ERR, "error saving row to persistent file\n");
        free(line);
        return SNMP_ERR_GENERR;
    }
    *buf++ = ' ';

    /*
     * prefix with column number, so we don't ever depend on
     * order saved.
     */
    buf += sprintf(buf, "%u:", COLUMN_IFALIAS);
    buf = read_config_save_octet_string(buf, rowreq_ctx->data.ifAlias,
                                        rowreq_ctx->data.ifAlias_len);
    *buf++ = ' ';

    /*
     * prefix with column number, so we don't ever depend on
     * order saved.
     */
    buf += sprintf(buf, "%u:%1lu ", COLUMN_IFLINKUPDOWNTRAPENABLE,
                   rowreq_ctx->data.ifLinkUpDownTrapEnable);

    /*
     * terminate and store the line
     */
    sprintf(buf, "%c\n", LINE_TERM_CHAR);
    DEBUGMSGTL(("ifXTable:save", "saving line '%s'\n", line));
    read_config_store((char *) type, line);

    /*
     * free memory
     */
    free(line);

    return SNMP_ERR_NOERROR;

}

static int
_ifXTable_save(int majorID, int minorID, void *serverarg, void *clientarg)
{
    char           *appname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
                                                    NETSNMP_DS_LIB_APPTYPE);

    /*
     * save all rows
     */
    CONTAINER_FOR_EACH((netsnmp_container *) clientarg,
                       (netsnmp_container_obj_func *)
                       _ifXTable_row_save, appname);

    /*
     * never fails 
     */
    return SNMPERR_SUCCESS;
}


static void
_ifXTable_restore(const char *token, char *buf)
{
    ifXTable_rowreq_ctx *context;
    netsnmp_container *container;
    netsnmp_index   index;
    u_int           col, len;

    if (strncmp(token, row_token, sizeof(row_token)) != 0) {
        snmp_log(LOG_ERR, "unknown token in _ifXTable_restore\n");
        return;
    }

    container = _ifXTable_container_get();
    if (NULL == container) {
        snmp_log(LOG_ERR, "null container in _ifXTable_restore\n");
        return;
    }

    DEBUGMSGTL(("ifXTable:restore", "parsing line '%s'\n", buf));

    /*
     * pull out index and find row
     */
    index.oids = NULL;
    buf = read_config_read_objid(buf, &index.oids, &index.len);
    if (NULL == buf) {
        snmp_log(LOG_ERR,
                 "error reading row index in _ifXTable_restore\n");
        return;
    }
    context = CONTAINER_FIND(container, &index);
    if (NULL == context) {
        snmp_log(LOG_ERR,
                 "error finding row index in _ifXTable_restore\n");
        return;
    }

    /*
     * get each column
     */
    buf = skip_white(buf);
    if ((NULL == buf) || !isdigit(*buf)) {
        snmp_log(LOG_ERR, "unexpected format1 in _ifXTable_restore\n");
        return;
    }

    /*
     * extract column, skip ':'
     */
    col = (u_int) strtol(buf, &buf, 10);
    if ((NULL == buf) || (*buf != ':') || (COLUMN_IFALIAS != col)) {
        snmp_log(LOG_ERR, "unexpected format2 in _ifXTable_restore\n");
        return;
    }
    ++buf;                      /* skip : */

    /*
     * parse value
     */
    DEBUGMSGTL(("ifXTable:restore", "parsing column %d\n", col));
    context->data.ifAlias_len = sizeof(context->data.ifAlias);
    buf = read_config_read_memory(ASN_OCTET_STR, buf,
                                  (char *) &context->data.ifAlias,
                                  (size_t *) &context->data.ifAlias_len);

    /*
     * extract column, skip ':'
     */
    col = (u_int) strtol(buf, &buf, 10);
    if ((NULL == buf) || (*buf != ':') ||
        (COLUMN_IFLINKUPDOWNTRAPENABLE != col)) {
        snmp_log(LOG_ERR, "unexpected format3 in _ifXTable_restore\n");
        return;
    }
    ++buf;                      /* skip : */

    /*
     * parse value
     */
    DEBUGMSGTL(("ifXTable:restore", "parsing column %d\n", col));
    len = sizeof(context->data.ifLinkUpDownTrapEnable);
    buf = read_config_read_memory(ASN_INTEGER, buf,
                                  (char *) &context->data.
                                  ifLinkUpDownTrapEnable, &len);

    /*
     * if the pointer is NULL and we didn't reach the
     * end of the line, something went wrong. Log message,
     * delete the row and bail.
     */
    if ((buf == NULL) || (*buf != LINE_TERM_CHAR)) {
        snmp_log(LOG_ERR, "unexpected format4 in _ifXTable_restore\n");
        return;
    }
}
