ifTable_interface.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:45k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  * Note: this file originally auto-generated by mib2c using
  3.  *       version : 1.42 $ of : mfd-interface.m2c,v $ 
  4.  *
  5.  * $Id: ifTable_interface.c,v 1.8.2.3 2005/03/29 21:05:24 nba Exp $
  6.  */
  7. /*
  8.  * *********************************************************************
  9.  * *********************************************************************
  10.  * *********************************************************************
  11.  * ***                                                               ***
  12.  * ***  NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE  ***
  13.  * ***                                                               ***
  14.  * ***                                                               ***
  15.  * ***       THIS FILE DOES NOT CONTAIN ANY USER EDITABLE CODE.      ***
  16.  * ***                                                               ***
  17.  * ***                                                               ***
  18.  * ***       THE GENERATED CODE IS INTERNAL IMPLEMENTATION, AND      ***
  19.  * ***                                                               ***
  20.  * ***                                                               ***
  21.  * ***    IS SUBJECT TO CHANGE WITHOUT WARNING IN FUTURE RELEASES.   ***
  22.  * ***                                                               ***
  23.  * ***                                                               ***
  24.  * *********************************************************************
  25.  * *********************************************************************
  26.  * *********************************************************************
  27.  */
  28. /*
  29.  * standard Net-SNMP includes 
  30.  */
  31. #include <net-snmp/net-snmp-config.h>
  32. #include <net-snmp/net-snmp-includes.h>
  33. #include <net-snmp/agent/net-snmp-agent-includes.h>
  34. /*
  35.  * include our parent header 
  36.  */
  37. #include "ifTable.h"
  38. #include <net-snmp/library/container.h>
  39. #include "ifTable_interface.h"
  40. /**********************************************************************
  41.  **********************************************************************
  42.  ***
  43.  *** Table ifTable
  44.  ***
  45.  **********************************************************************
  46.  **********************************************************************/
  47. /*
  48.  * ifTable is subid 2 of interfaces.
  49.  * Its status is Current.
  50.  * OID: .1.3.6.1.2.1.2.2, length: 8
  51.  */
  52. typedef struct ifTable_interface_ctx_s {
  53.     netsnmp_container *container;
  54.     netsnmp_cache  *cache;      /* optional cache */
  55.     ifTable_registration_ptr user_ctx;
  56.     netsnmp_table_registration_info tbl_info;
  57.     netsnmp_baby_steps_access_methods access_multiplexer;
  58. } ifTable_interface_ctx;
  59. static ifTable_interface_ctx ifTable_if_ctx;
  60. static void     _ifTable_container_init(ifTable_interface_ctx * if_ctx);
  61. static Netsnmp_Node_Handler _mfd_ifTable_pre_request;
  62. static Netsnmp_Node_Handler _mfd_ifTable_post_request;
  63. static Netsnmp_Node_Handler _mfd_ifTable_object_lookup;
  64. static Netsnmp_Node_Handler _mfd_ifTable_get_values;
  65. static Netsnmp_Node_Handler _mfd_ifTable_check_objects;
  66. static Netsnmp_Node_Handler _mfd_ifTable_undo_setup;
  67. static Netsnmp_Node_Handler _mfd_ifTable_set_values;
  68. static Netsnmp_Node_Handler _mfd_ifTable_undo_cleanup;
  69. static Netsnmp_Node_Handler _mfd_ifTable_undo_values;
  70. static Netsnmp_Node_Handler _mfd_ifTable_commit;
  71. static Netsnmp_Node_Handler _mfd_ifTable_undo_commit;
  72. static Netsnmp_Node_Handler _mfd_ifTable_check_dependencies;
  73. NETSNMP_STATIC_INLINE int _ifTable_undo_column(ifTable_rowreq_ctx *
  74.                                                rowreq_ctx,
  75.                                                netsnmp_variable_list * var,
  76.                                                int column);
  77. ifTable_data   *ifTable_allocate_data(void);
  78. /**
  79.  * common init of container for ifTable and ifXTable
  80.  */
  81. void
  82. if_mib_container_init(void)
  83. {
  84.     static int done = 0;
  85.     if (done)
  86.         return;
  87.     DEBUGMSGTL(("internal:ifTable:ifTable_container_init", "calledn"));
  88.     done = 1;
  89.     /*
  90.      * set up the container. This is outside the rewrite ifdef, because
  91.      * the container is used by the ifXTable too..
  92.      */
  93.     _ifTable_container_init(&ifTable_if_ctx);
  94. }
  95. /**
  96.  * @internal
  97.  * Initialize the table ifTable 
  98.  *    (Define its contents and how it's structured)
  99.  */
  100. void
  101. _ifTable_initialize_interface(ifTable_registration_ptr reg_ptr,
  102.                               u_long flags)
  103. {
  104.     netsnmp_baby_steps_access_methods *access_multiplexer =
  105.         &ifTable_if_ctx.access_multiplexer;
  106.     netsnmp_table_registration_info *tbl_info = &ifTable_if_ctx.tbl_info;
  107.     netsnmp_handler_registration *reginfo;
  108.     netsnmp_mib_handler *handler;
  109.     int             mfd_modes = 0;
  110.     DEBUGMSGTL(("internal:ifTable:_ifTable_initialize_interface",
  111.                 "calledn"));
  112.     (void) if_mib_container_init();
  113.     if (NULL == ifTable_if_ctx.container)
  114.         return; /* msg already logged */
  115. #ifdef NETSNMP_ENABLE_MFD_REWRITES
  116.     /*************************************************
  117.      *
  118.      * save interface context for ifTable
  119.      */
  120.     /*
  121.      * Setting up the table's definition
  122.      */
  123.     netsnmp_table_helper_add_indexes(tbl_info, ASN_INTEGER,
  124.                                                /** index: ifIndex */
  125.                                      0);
  126.     /*
  127.      * Define the minimum and maximum accessible columns.  This
  128.      * optimizes retrival. 
  129.      */
  130.     tbl_info->min_column = IFTABLE_MIN_COL;
  131.     tbl_info->max_column = IFTABLE_MAX_COL;
  132.     /*
  133.      * save users context
  134.      */
  135.     ifTable_if_ctx.user_ctx = reg_ptr;
  136.     /*
  137.      * call data access initialization code
  138.      */
  139.     ifTable_init_data(reg_ptr);
  140.     /*
  141.      * access_multiplexer: REQUIRED wrapper for get request handling
  142.      */
  143.     access_multiplexer->object_lookup = _mfd_ifTable_object_lookup;
  144.     access_multiplexer->get_values = _mfd_ifTable_get_values;
  145.     /*
  146.      * no wrappers yet
  147.      */
  148.     access_multiplexer->pre_request = _mfd_ifTable_pre_request;
  149.     access_multiplexer->post_request = _mfd_ifTable_post_request;
  150.     /*
  151.      * REQUIRED wrappers for set request handling
  152.      */
  153.     access_multiplexer->object_syntax_checks = _mfd_ifTable_check_objects;
  154.     access_multiplexer->undo_setup = _mfd_ifTable_undo_setup;
  155.     access_multiplexer->undo_cleanup = _mfd_ifTable_undo_cleanup;
  156.     access_multiplexer->set_values = _mfd_ifTable_set_values;
  157.     access_multiplexer->undo_sets = _mfd_ifTable_undo_values;
  158.     /*
  159.      * no wrappers yet
  160.      */
  161.     access_multiplexer->commit = _mfd_ifTable_commit;
  162.     access_multiplexer->undo_commit = _mfd_ifTable_undo_commit;
  163.     /*
  164.      * REQUIRED for tables with dependencies
  165.      */
  166.     access_multiplexer->consistency_checks =
  167.         _mfd_ifTable_check_dependencies;
  168.     /*************************************************
  169.      *
  170.      * Create a registration, save our reg data, register table.
  171.      */
  172.     DEBUGMSGTL(("ifTable:init_ifTable",
  173.                 "Registering ifTable as a mibs-for-dummies table.n"));
  174.     handler =
  175.         netsnmp_baby_steps_access_multiplexer_get(access_multiplexer);
  176.     reginfo =
  177.         netsnmp_handler_registration_create("ifTable", handler,
  178.                                             ifTable_oid, ifTable_oid_size,
  179.                                             HANDLER_CAN_BABY_STEP |
  180.                                             HANDLER_CAN_RWRITE);
  181.     if (NULL == reginfo) {
  182.         snmp_log(LOG_ERR, "error registering table ifTablen");
  183.         return;
  184.     }
  185.     reginfo->my_reg_void = &ifTable_if_ctx;
  186.     /*************************************************
  187.      *
  188.      * set up baby steps handler, create it and inject it
  189.      */
  190.     if (access_multiplexer->object_lookup)
  191.         mfd_modes |= BABY_STEP_OBJECT_LOOKUP;
  192.     if (access_multiplexer->set_values)
  193.         mfd_modes |= BABY_STEP_SET_VALUES;
  194.     if (access_multiplexer->irreversible_commit)
  195.         mfd_modes |= BABY_STEP_IRREVERSIBLE_COMMIT;
  196.     if (access_multiplexer->object_syntax_checks)
  197.         mfd_modes |= BABY_STEP_CHECK_OBJECT;
  198.     if (access_multiplexer->pre_request)
  199.         mfd_modes |= BABY_STEP_PRE_REQUEST;
  200.     if (access_multiplexer->post_request)
  201.         mfd_modes |= BABY_STEP_POST_REQUEST;
  202.     if (access_multiplexer->undo_setup)
  203.         mfd_modes |= BABY_STEP_UNDO_SETUP;
  204.     if (access_multiplexer->undo_cleanup)
  205.         mfd_modes |= BABY_STEP_UNDO_CLEANUP;
  206.     if (access_multiplexer->undo_sets)
  207.         mfd_modes |= BABY_STEP_UNDO_SETS;
  208.     if (access_multiplexer->row_creation)
  209.         mfd_modes |= BABY_STEP_ROW_CREATE;
  210.     if (access_multiplexer->consistency_checks)
  211.         mfd_modes |= BABY_STEP_CHECK_CONSISTENCY;
  212.     if (access_multiplexer->commit)
  213.         mfd_modes |= BABY_STEP_COMMIT;
  214.     if (access_multiplexer->undo_commit)
  215.         mfd_modes |= BABY_STEP_UNDO_COMMIT;
  216.     handler = netsnmp_baby_steps_handler_get(mfd_modes);
  217.     netsnmp_inject_handler(reginfo, handler);
  218.     /*************************************************
  219.      *
  220.      * inject row_merge helper with prefix rootoid_len + 2 (entry.col)
  221.      */
  222.     handler = netsnmp_get_row_merge_handler(reginfo->rootoid_len + 2);
  223.     netsnmp_inject_handler(reginfo, handler);
  224.     /*************************************************
  225.      *
  226.      * inject container_table helper
  227.      */
  228.     handler =
  229.         netsnmp_container_table_handler_get(tbl_info,
  230.                                             ifTable_if_ctx.container,
  231.                                             TABLE_CONTAINER_KEY_NETSNMP_INDEX);
  232.     netsnmp_inject_handler(reginfo, handler);
  233.     /*************************************************
  234.      *
  235.      * inject cache helper
  236.      */
  237.     if (NULL != ifTable_if_ctx.cache) {
  238.         handler = netsnmp_cache_handler_get(ifTable_if_ctx.cache);
  239.         netsnmp_inject_handler(reginfo, handler);
  240.     }
  241.     /*
  242.      * register table
  243.      */
  244.     netsnmp_register_table(reginfo, tbl_info);
  245. #endif                          /* NETSNMP_ENABLE_MFD_REWRITES */
  246. }                               /* _ifTable_initialize_interface */
  247. void
  248. ifTable_valid_columns_set(netsnmp_column_info *vc)
  249. {
  250.     ifTable_if_ctx.tbl_info.valid_columns = vc;
  251. }                               /* ifTable_valid_columns_set */
  252. /**
  253.  * @internal
  254.  * convert the index component stored in the context to an oid
  255.  */
  256. int
  257. ifTable_index_to_oid(netsnmp_index * oid_idx, ifTable_mib_index * mib_idx)
  258. {
  259.     int             err = SNMP_ERR_NOERROR;
  260.     /*
  261.      * temp storage for parsing indexes
  262.      */
  263.     /*
  264.      * ifIndex(1)/InterfaceIndex/ASN_INTEGER/long(long)//l/A/w/e/R/d/H
  265.      */
  266.     netsnmp_variable_list var_ifIndex;
  267.     /*
  268.      * set up varbinds
  269.      */
  270.     memset(&var_ifIndex, 0x00, sizeof(var_ifIndex));
  271.     var_ifIndex.type = ASN_INTEGER;
  272.     /*
  273.      * chain temp index varbinds together
  274.      */
  275.     var_ifIndex.next_variable = NULL;
  276.     DEBUGMSGTL(("verbose:ifTable:ifTable_index_to_oid", "calledn"));
  277.     /*
  278.      * ifIndex(1)/InterfaceIndex/ASN_INTEGER/long(long)//l/A/w/e/R/d/H 
  279.      */
  280.     snmp_set_var_value(&var_ifIndex, (u_char *) & mib_idx->ifIndex,
  281.                        sizeof(mib_idx->ifIndex));
  282.     err = build_oid_noalloc(oid_idx->oids, oid_idx->len, &oid_idx->len,
  283.                             NULL, 0, &var_ifIndex);
  284.     if (err)
  285.         snmp_log(LOG_ERR, "error %d converting index to oidn", err);
  286.     /*
  287.      * parsing may have allocated memory. free it.
  288.      */
  289.     snmp_reset_var_buffers(&var_ifIndex);
  290.     return err;
  291. }                               /* ifTable_index_to_oid */
  292. /**
  293.  * extract ifTable indexes from a netsnmp_index
  294.  *
  295.  * @retval SNMP_ERR_NOERROR  : no error
  296.  * @retval SNMP_ERR_GENERR   : error
  297.  */
  298. int
  299. ifTable_index_from_oid(netsnmp_index * oid_idx,
  300.                        ifTable_mib_index * mib_idx)
  301. {
  302.     int             err = SNMP_ERR_NOERROR;
  303.     /*
  304.      * temp storage for parsing indexes
  305.      */
  306.     /*
  307.      * ifIndex(1)/InterfaceIndex/ASN_INTEGER/long(long)//l/A/w/e/R/d/H
  308.      */
  309.     netsnmp_variable_list var_ifIndex;
  310.     /*
  311.      * set up varbinds
  312.      */
  313.     memset(&var_ifIndex, 0x00, sizeof(var_ifIndex));
  314.     var_ifIndex.type = ASN_INTEGER;
  315.     /*
  316.      * chain temp index varbinds together
  317.      */
  318.     var_ifIndex.next_variable = NULL;
  319.     DEBUGMSGTL(("verbose:ifTable:ifTable_index_from_oid", "calledn"));
  320.     /*
  321.      * parse the oid into the individual index components
  322.      */
  323.     err = parse_oid_indexes(oid_idx->oids, oid_idx->len, &var_ifIndex);
  324.     if (err == SNMP_ERR_NOERROR) {
  325.         /*
  326.          * copy out values
  327.          */
  328.         mib_idx->ifIndex = *((long *) var_ifIndex.val.string);
  329.     }
  330.     /*
  331.      * parsing may have allocated memory. free it.
  332.      */
  333.     snmp_reset_var_buffers(&var_ifIndex);
  334.     return err;
  335. }                               /* ifTable_index_from_oid */
  336. /*
  337.  * ---------------------------------------------------------------------
  338.  * * TODO:200:r: Implement ifTable data context functions.
  339.  */
  340. /*
  341.  * ifTable_allocate_data
  342.  *
  343.  * Purpose: create new ifTable_data.
  344.  */
  345. ifTable_data   *
  346. ifTable_allocate_data(void)
  347. {
  348.     /*
  349.      * TODO:201:r: |-> allocate memory for the ifTable data context.
  350.      */
  351.     ifTable_data   *rtn = SNMP_MALLOC_TYPEDEF(ifTable_data);
  352.     DEBUGMSGTL(("verbose:ifTable:ifTable_allocate_data", "calledn"));
  353.     if (NULL == rtn) {
  354.         snmp_log(LOG_ERR, "unable to malloc memory for new "
  355.                  "ifTable_data.n");
  356.     }
  357.     return rtn;
  358. }                               /* ifTable_allocate_data */
  359. /*
  360.  * ifTable_release_data
  361.  *
  362.  * Purpose: release ifTable data.
  363.  */
  364. void
  365. ifTable_release_data(ifTable_data * data)
  366. {
  367.     DEBUGMSGTL(("verbose:ifTable:ifTable_release_data", "calledn"));
  368.     /*
  369.      * TODO:202:r: |-> release memory for the ifTable data context.
  370.      */
  371.     free(data);
  372. }                               /* ifTable_release_data */
  373. /*
  374.  *********************************************************************
  375.  * @internal
  376.  * allocate resources for a ifTable_rowreq_ctx
  377.  */
  378. ifTable_rowreq_ctx *
  379. ifTable_allocate_rowreq_ctx(void *user_init_ctx)
  380. {
  381.     ifTable_rowreq_ctx *rowreq_ctx =
  382.         SNMP_MALLOC_TYPEDEF(ifTable_rowreq_ctx);
  383.     DEBUGMSGTL(("internal:ifTable:ifTable_allocate_rowreq_ctx",
  384.                 "calledn"));
  385.     if (NULL == rowreq_ctx) {
  386.         snmp_log(LOG_ERR, "Couldn't allocate memory for a "
  387.                  "ifTable_rowreq_ctx.n");
  388.     }
  389.     rowreq_ctx->oid_idx.oids = rowreq_ctx->oid_tmp;
  390.     rowreq_ctx->ifTable_data_list = NULL;
  391.     rowreq_ctx->ifTable_reg = ifTable_if_ctx.user_ctx;
  392.     if (SNMPERR_SUCCESS !=
  393.         ifTable_rowreq_ctx_init(rowreq_ctx, user_init_ctx)) {
  394.         ifTable_release_rowreq_ctx(rowreq_ctx);
  395.         rowreq_ctx = NULL;
  396.     }
  397.     return rowreq_ctx;
  398. }                               /* ifTable_allocate_rowreq_ctx */
  399. /*
  400.  * @internal
  401.  * release resources for a ifTable_rowreq_ctx
  402.  */
  403. void
  404. ifTable_release_rowreq_ctx(ifTable_rowreq_ctx * rowreq_ctx)
  405. {
  406.     DEBUGMSGTL(("internal:ifTable:ifTable_release_rowreq_ctx",
  407.                 "calledn"));
  408.     netsnmp_assert(NULL != rowreq_ctx);
  409.     ifTable_rowreq_ctx_cleanup(rowreq_ctx);
  410.     if (rowreq_ctx->undo) {
  411.         ifTable_release_data(rowreq_ctx->undo);
  412.         rowreq_ctx->undo = NULL;
  413.     }
  414.     /*
  415.      * free index oid pointer
  416.      */
  417.     if (rowreq_ctx->oid_idx.oids != rowreq_ctx->oid_tmp)
  418.         free(rowreq_ctx->oid_idx.oids);
  419.     SNMP_FREE(rowreq_ctx);
  420. }                               /* ifTable_release_rowreq_ctx */
  421. /**
  422.  * @internal
  423.  * wrapper
  424.  */
  425. static int
  426. _mfd_ifTable_pre_request(netsnmp_mib_handler *handler,
  427.                          netsnmp_handler_registration *reginfo,
  428.                          netsnmp_agent_request_info *agtreq_info,
  429.                          netsnmp_request_info *requests)
  430. {
  431.     int             rc = ifTable_pre_request(ifTable_if_ctx.user_ctx);
  432.     if (MFD_SUCCESS != rc) {
  433.         /*
  434.          * nothing we can do about it but log it
  435.          */
  436.         DEBUGMSGTL(("internal:ifTable", "error %d from "
  437.                     "ifTable_pre_requestn", rc));
  438.         netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
  439.     }
  440.     return SNMP_ERR_NOERROR;
  441. }                               /* _mfd_ifTable_pre_request */
  442. /**
  443.  * @internal
  444.  * wrapper
  445.  */
  446. static int
  447. _mfd_ifTable_post_request(netsnmp_mib_handler *handler,
  448.                           netsnmp_handler_registration *reginfo,
  449.                           netsnmp_agent_request_info *agtreq_info,
  450.                           netsnmp_request_info *requests)
  451. {
  452.     ifTable_rowreq_ctx *rowreq_ctx;
  453.     int             rc = ifTable_post_request(ifTable_if_ctx.user_ctx);
  454.     if (MFD_SUCCESS != rc) {
  455.         /*
  456.          * nothing we can do about it but log it
  457.          */
  458.         DEBUGMSGTL(("internal:ifTable", "error %d from "
  459.                     "ifTable_post_requestn", rc));
  460.     }
  461.     /*
  462.      * if it was set, clear row created flag.
  463.      */
  464.     rowreq_ctx = netsnmp_container_table_row_extract(requests);
  465.     if ((NULL != rowreq_ctx)
  466.         && (rowreq_ctx->rowreq_flags & MFD_ROW_CREATED))
  467.         rowreq_ctx->rowreq_flags &= ~MFD_ROW_CREATED;
  468.     return SNMP_ERR_NOERROR;
  469. }                               /* _mfd_ifTable_post_request */
  470. /**
  471.  * @internal
  472.  * wrapper
  473.  */
  474. static int
  475. _mfd_ifTable_object_lookup(netsnmp_mib_handler *handler,
  476.                            netsnmp_handler_registration *reginfo,
  477.                            netsnmp_agent_request_info *agtreq_info,
  478.                            netsnmp_request_info *requests)
  479. {
  480.     ifTable_rowreq_ctx *rowreq_ctx =
  481.         netsnmp_container_table_row_extract(requests);
  482.     DEBUGMSGTL(("internal:ifTable:_mfd_ifTable_object_lookup",
  483.                 "calledn"));
  484.     /*
  485.      * get our context from mfd
  486.      * ifTable_interface_ctx *if_ctx =
  487.      *             (ifTable_interface_ctx *)reginfo->my_reg_void;
  488.      */
  489.     if (NULL == rowreq_ctx) {
  490.         netsnmp_request_set_error_all(requests, SNMP_ERR_NOCREATION);
  491.     } else {
  492.         ifTable_row_prep(rowreq_ctx);
  493.     }
  494.     return SNMP_ERR_NOERROR;
  495. }                               /* _mfd_ifTable_object_lookup */
  496. /***********************************************************************
  497.  *
  498.  * GET processing
  499.  *
  500.  ***********************************************************************/
  501. /*
  502.  * @internal
  503.  * Retrieve the value for a particular column
  504.  */
  505. NETSNMP_STATIC_INLINE int
  506. _ifTable_get_column(ifTable_rowreq_ctx * rowreq_ctx,
  507.                     netsnmp_variable_list * var, int column)
  508. {
  509.     int             rc = SNMPERR_SUCCESS;
  510.     DEBUGMSGTL(("internal:ifTable:_mfd_ifTable_get_column", "calledn"));
  511.     netsnmp_assert(NULL != rowreq_ctx);
  512.     switch (column) {
  513.         /*
  514.          * (INDEX) ifIndex(1)/InterfaceIndex/ASN_INTEGER/long(long)//l/A/w/e/R/d/H 
  515.          */
  516.     case COLUMN_IFINDEX:
  517.         var->type = ASN_INTEGER;
  518.         var->val_len = sizeof(long);
  519.         (*var->val.integer) = rowreq_ctx->tbl_idx.ifIndex;
  520.         break;
  521.         /*
  522.          * ifDescr(2)/DisplayString/ASN_OCTET_STR/char(char)//L/A/w/e/R/d/H 
  523.          */
  524.     case COLUMN_IFDESCR:
  525.         var->type = ASN_OCTET_STR;
  526.         rc = ifDescr_get(rowreq_ctx, (char **) &var->val.string,
  527.                          &var->val_len);
  528.         break;
  529.         /*
  530.          * ifType(3)/IANAifType/ASN_INTEGER/long(u_long)//l/A/w/E/r/d/h 
  531.          */
  532.     case COLUMN_IFTYPE:
  533.         var->val_len = sizeof(u_long);
  534.         var->type = ASN_INTEGER;
  535.         rc = ifType_get(rowreq_ctx, (u_long *) var->val.string);
  536.         break;
  537.         /*
  538.          * ifMtu(4)/INTEGER32/ASN_INTEGER/long(long)//l/A/w/e/r/d/h 
  539.          */
  540.     case COLUMN_IFMTU:
  541.         var->val_len = sizeof(long);
  542.         var->type = ASN_INTEGER;
  543.         rc = ifMtu_get(rowreq_ctx, (long *) var->val.string);
  544.         break;
  545.         /*
  546.          * ifSpeed(5)/GAUGE/ASN_GAUGE/u_long(u_long)//l/A/w/e/r/d/h 
  547.          */
  548.     case COLUMN_IFSPEED:
  549.         var->val_len = sizeof(u_long);
  550.         var->type = ASN_GAUGE;
  551.         rc = ifSpeed_get(rowreq_ctx, (u_long *) var->val.string);
  552.         break;
  553.         /*
  554.          * ifPhysAddress(6)/PhysAddress/ASN_OCTET_STR/char(char)//L/A/w/e/r/d/H 
  555.          */
  556.     case COLUMN_IFPHYSADDRESS:
  557.         var->type = ASN_OCTET_STR;
  558.         rc = ifPhysAddress_get(rowreq_ctx, (char **) &var->val.string,
  559.                                &var->val_len);
  560.         break;
  561.         /*
  562.          * ifAdminStatus(7)/INTEGER/ASN_INTEGER/long(u_long)//l/A/W/E/r/d/h 
  563.          */
  564.     case COLUMN_IFADMINSTATUS:
  565.         var->val_len = sizeof(u_long);
  566.         var->type = ASN_INTEGER;
  567.         rc = ifAdminStatus_get(rowreq_ctx, (u_long *) var->val.string);
  568.         break;
  569.         /*
  570.          * ifOperStatus(8)/INTEGER/ASN_INTEGER/long(u_long)//l/A/w/E/r/d/h 
  571.          */
  572.     case COLUMN_IFOPERSTATUS:
  573.         var->val_len = sizeof(u_long);
  574.         var->type = ASN_INTEGER;
  575.         rc = ifOperStatus_get(rowreq_ctx, (u_long *) var->val.string);
  576.         break;
  577.         /*
  578.          * ifLastChange(9)/TICKS/ASN_TIMETICKS/u_long(u_long)//l/A/w/e/r/d/h 
  579.          */
  580.     case COLUMN_IFLASTCHANGE:
  581.         var->val_len = sizeof(u_long);
  582.         var->type = ASN_TIMETICKS;
  583.         rc = ifLastChange_get(rowreq_ctx, (u_long *) var->val.string);
  584.         break;
  585.         /*
  586.          * ifInOctets(10)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h 
  587.          */
  588.     case COLUMN_IFINOCTETS:
  589.         var->val_len = sizeof(u_long);
  590.         var->type = ASN_COUNTER;
  591.         rc = ifInOctets_get(rowreq_ctx, (u_long *) var->val.string);
  592.         break;
  593.         /*
  594.          * ifInUcastPkts(11)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h 
  595.          */
  596.     case COLUMN_IFINUCASTPKTS:
  597.         var->val_len = sizeof(u_long);
  598.         var->type = ASN_COUNTER;
  599.         rc = ifInUcastPkts_get(rowreq_ctx, (u_long *) var->val.string);
  600.         break;
  601.         /*
  602.          * ifInNUcastPkts(12)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h 
  603.          */
  604.     case COLUMN_IFINNUCASTPKTS:
  605.         var->val_len = sizeof(u_long);
  606.         var->type = ASN_COUNTER;
  607.         rc = ifInNUcastPkts_get(rowreq_ctx, (u_long *) var->val.string);
  608.         break;
  609.         /*
  610.          * ifInDiscards(13)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h 
  611.          */
  612.     case COLUMN_IFINDISCARDS:
  613.         var->val_len = sizeof(u_long);
  614.         var->type = ASN_COUNTER;
  615.         rc = ifInDiscards_get(rowreq_ctx, (u_long *) var->val.string);
  616.         break;
  617.         /*
  618.          * ifInErrors(14)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h 
  619.          */
  620.     case COLUMN_IFINERRORS:
  621.         var->val_len = sizeof(u_long);
  622.         var->type = ASN_COUNTER;
  623.         rc = ifInErrors_get(rowreq_ctx, (u_long *) var->val.string);
  624.         break;
  625.         /*
  626.          * ifInUnknownProtos(15)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h 
  627.          */
  628.     case COLUMN_IFINUNKNOWNPROTOS:
  629.         var->val_len = sizeof(u_long);
  630.         var->type = ASN_COUNTER;
  631.         rc = ifInUnknownProtos_get(rowreq_ctx, (u_long *) var->val.string);
  632.         break;
  633.         /*
  634.          * ifOutOctets(16)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h 
  635.          */
  636.     case COLUMN_IFOUTOCTETS:
  637.         var->val_len = sizeof(u_long);
  638.         var->type = ASN_COUNTER;
  639.         rc = ifOutOctets_get(rowreq_ctx, (u_long *) var->val.string);
  640.         break;
  641.         /*
  642.          * ifOutUcastPkts(17)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h 
  643.          */
  644.     case COLUMN_IFOUTUCASTPKTS:
  645.         var->val_len = sizeof(u_long);
  646.         var->type = ASN_COUNTER;
  647.         rc = ifOutUcastPkts_get(rowreq_ctx, (u_long *) var->val.string);
  648.         break;
  649.         /*
  650.          * ifOutNUcastPkts(18)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h 
  651.          */
  652.     case COLUMN_IFOUTNUCASTPKTS:
  653.         var->val_len = sizeof(u_long);
  654.         var->type = ASN_COUNTER;
  655.         rc = ifOutNUcastPkts_get(rowreq_ctx, (u_long *) var->val.string);
  656.         break;
  657.         /*
  658.          * ifOutDiscards(19)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h 
  659.          */
  660.     case COLUMN_IFOUTDISCARDS:
  661.         var->val_len = sizeof(u_long);
  662.         var->type = ASN_COUNTER;
  663.         rc = ifOutDiscards_get(rowreq_ctx, (u_long *) var->val.string);
  664.         break;
  665.         /*
  666.          * ifOutErrors(20)/COUNTER/ASN_COUNTER/u_long(u_long)//l/A/w/e/r/d/h 
  667.          */
  668.     case COLUMN_IFOUTERRORS:
  669.         var->val_len = sizeof(u_long);
  670.         var->type = ASN_COUNTER;
  671.         rc = ifOutErrors_get(rowreq_ctx, (u_long *) var->val.string);
  672.         break;
  673.         /*
  674.          * ifOutQLen(21)/GAUGE/ASN_GAUGE/u_long(u_long)//l/A/w/e/r/d/h 
  675.          */
  676.     case COLUMN_IFOUTQLEN:
  677.         var->val_len = sizeof(u_long);
  678.         var->type = ASN_GAUGE;
  679.         rc = ifOutQLen_get(rowreq_ctx, (u_long *) var->val.string);
  680.         break;
  681.         /*
  682.          * ifSpecific(22)/OBJECTID/ASN_OBJECT_ID/oid(oid)//L/A/w/e/r/d/h 
  683.          */
  684.     case COLUMN_IFSPECIFIC:
  685.         var->type = ASN_OBJECT_ID;
  686.         rc = ifSpecific_get(rowreq_ctx, (oid **) & var->val.string,
  687.                             &var->val_len);
  688.         break;
  689.     default:
  690.         snmp_log(LOG_ERR, "unknown column %d in _ifTable_get_columnn",
  691.                  column);
  692.         break;
  693.     }
  694.     return rc;
  695. }                               /* _ifTable_get_column */
  696. int
  697. _mfd_ifTable_get_values(netsnmp_mib_handler *handler,
  698.                         netsnmp_handler_registration *reginfo,
  699.                         netsnmp_agent_request_info *agtreq_info,
  700.                         netsnmp_request_info *requests)
  701. {
  702.     ifTable_rowreq_ctx *rowreq_ctx =
  703.         netsnmp_container_table_row_extract(requests);
  704.     netsnmp_table_request_info *tri;
  705.     u_char         *old_string;
  706.     void            (*dataFreeHook) (void *);
  707.     int             rc;
  708.     DEBUGMSGTL(("internal:ifTable:_mfd_ifTable_get_values", "calledn"));
  709.     netsnmp_assert(NULL != rowreq_ctx);
  710.     for (; requests; requests = requests->next) {
  711.         /*
  712.          * save old pointer, so we can free it if replaced
  713.          */
  714.         old_string = requests->requestvb->val.string;
  715.         dataFreeHook = requests->requestvb->dataFreeHook;
  716.         if (NULL == requests->requestvb->val.string) {
  717.             requests->requestvb->val.string = requests->requestvb->buf;
  718.             requests->requestvb->val_len =
  719.                 sizeof(requests->requestvb->buf);
  720.         } else if (requests->requestvb->buf ==
  721.                    requests->requestvb->val.string) {
  722.             if (requests->requestvb->val_len !=
  723.                 sizeof(requests->requestvb->buf))
  724.                 requests->requestvb->val_len =
  725.                     sizeof(requests->requestvb->buf);
  726.         }
  727.         /*
  728.          * get column data
  729.          */
  730.         tri = netsnmp_extract_table_info(requests);
  731.         if (NULL == tri)
  732.             continue;
  733.         rc = _ifTable_get_column(rowreq_ctx, requests->requestvb,
  734.                                  tri->colnum);
  735.         if (rc) {
  736.             if (MFD_SKIP == rc) {
  737.                 requests->requestvb->type = ASN_PRIV_RETRY;
  738.                 rc = SNMP_ERR_NOERROR;
  739.             }
  740.         } else if (NULL == requests->requestvb->val.string) {
  741.             snmp_log(LOG_ERR, "NULL varbind data pointer!n");
  742.             rc = SNMP_ERR_GENERR;
  743.         }
  744.         if (rc)
  745.             netsnmp_request_set_error(requests, SNMP_VALIDATE_ERR(rc));
  746.         /*
  747.          * if the buffer wasn't used previously for the old data (i.e. it
  748.          * was allcoated memory)  and the get routine replaced the pointer,
  749.          * we need to free the previous pointer.
  750.          */
  751.         if (old_string && (old_string != requests->requestvb->buf) &&
  752.             (requests->requestvb->val.string != old_string)) {
  753.             if (dataFreeHook)
  754.                 (*dataFreeHook) (old_string);
  755.             else
  756.                 free(old_string);
  757.         }
  758.     }                           /* for results */
  759.     return SNMP_ERR_NOERROR;
  760. }                               /* _mfd_ifTable_get_values */
  761. /***********************************************************************
  762.  *
  763.  * SET processing
  764.  *
  765.  ***********************************************************************/
  766. /*----------------------------------------------------------------------
  767.  *
  768.  * SET: Syntax checks
  769.  *
  770.  *---------------------------------------------------------------------*/
  771. /*
  772.  * @internal
  773.  * Check the syntax for a particular column
  774.  */
  775. NETSNMP_STATIC_INLINE int
  776. _ifTable_check_column(ifTable_rowreq_ctx * rowreq_ctx,
  777.                       netsnmp_variable_list * var, int column)
  778. {
  779.     int             rc = SNMPERR_SUCCESS;
  780.     DEBUGMSGTL(("internal:ifTable:_ifTable_check_column", "calledn"));
  781.     netsnmp_assert(NULL != rowreq_ctx);
  782.     switch (column) {
  783.         /*
  784.          * ifAdminStatus(7)/INTEGER/ASN_INTEGER/long(u_long)//l/A/W/E/r/d/h 
  785.          */
  786.     case COLUMN_IFADMINSTATUS:
  787.         /** special case: we are using exernal storage w/smaller data size
  788.          ** for storage, so we can't use sizeof on data context. So we
  789.          ** just check that it's the expected size. The enum tests below
  790.          ** will ensure that there is no data overflow. */
  791.         rc = netsnmp_check_vb_type_and_size(var, ASN_INTEGER,
  792.                                             sizeof(u_long));
  793.         if (SNMPERR_SUCCESS == rc) {
  794.             /*
  795.              * check that the value is one of defined enums 
  796.              */
  797.             if (1 && (*var->val.integer != IFADMINSTATUS_UP)
  798.                 && (*var->val.integer != IFADMINSTATUS_DOWN)
  799.                 && (*var->val.integer != IFADMINSTATUS_TESTING)
  800.                 ) {
  801.                 rc = SNMP_ERR_WRONGVALUE;
  802.             }
  803.         }
  804.         if (SNMPERR_SUCCESS == rc) {
  805.             rc = ifAdminStatus_check_value(rowreq_ctx,
  806.                                            *((u_long *) var->val.string));
  807.             if ((MFD_SUCCESS != rc) && (MFD_NOT_VALID_EVER != rc)
  808.                 && (MFD_NOT_VALID_NOW != rc)) {
  809.                 snmp_log(LOG_ERR,
  810.                          "bad rc %d from ifAdminStatus_check_valuen", rc);
  811.                 rc = SNMP_ERR_GENERR;
  812.             }
  813.         }
  814.         break;
  815.     default: /** We shouldn't get here */
  816.         rc = SNMP_ERR_GENERR;
  817.         snmp_log(LOG_ERR, "unknown column %d in _ifTable_check_columnn",
  818.                  column);
  819.     }
  820.     return rc;
  821. }                               /* _ifTable_check_column */
  822. int
  823. _mfd_ifTable_check_objects(netsnmp_mib_handler *handler,
  824.                            netsnmp_handler_registration *reginfo,
  825.                            netsnmp_agent_request_info *agtreq_info,
  826.                            netsnmp_request_info *requests)
  827. {
  828.     ifTable_rowreq_ctx *rowreq_ctx =
  829.         netsnmp_container_table_row_extract(requests);
  830.     netsnmp_table_request_info *tri;
  831.     int             rc;
  832.     DEBUGMSGTL(("internal:ifTable:_mfd_ifTable_check_objects",
  833.                 "calledn"));
  834.     netsnmp_assert(NULL != rowreq_ctx);
  835.     for (; requests; requests = requests->next) {
  836.         /*
  837.          * get column number from table request info, and check that column
  838.          */
  839.         tri = netsnmp_extract_table_info(requests);
  840.         if (NULL == tri)
  841.             continue;
  842.         rc = _ifTable_check_column(rowreq_ctx, requests->requestvb,
  843.                                    tri->colnum);
  844.         if (rc) {
  845.             netsnmp_request_set_error(requests, SNMP_VALIDATE_ERR(rc));
  846.             break;
  847.         }
  848.     }                           /* for results */
  849.     return SNMP_ERR_NOERROR;
  850. }                               /* _mfd_ifTable_check_objects */
  851. /*----------------------------------------------------------------------
  852.  *
  853.  * SET: check dependencies
  854.  *
  855.  *---------------------------------------------------------------------*/
  856. /*
  857.  * @internal
  858.  * Check dependencies wrapper
  859.  */
  860. static int
  861. _mfd_ifTable_check_dependencies(netsnmp_mib_handler *handler,
  862.                                 netsnmp_handler_registration *reginfo,
  863.                                 netsnmp_agent_request_info *agtreq_info,
  864.                                 netsnmp_request_info *requests)
  865. {
  866.     int             rc;
  867.     ifTable_rowreq_ctx *rowreq_ctx =
  868.         netsnmp_container_table_row_extract(requests);
  869.     DEBUGMSGTL(("internal:ifTable:_mfd_ifTable_check_dependencies",
  870.                 "calledn"));
  871.     netsnmp_assert(NULL != rowreq_ctx);
  872.     rc = ifTable_check_dependencies(rowreq_ctx);
  873.     if (rc) {
  874.         DEBUGMSGTL(("verbose:ifTable:mfd", "error %d from "
  875.                     "ifTable_check_dependenciesn", rc));
  876.         netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
  877.     }
  878.     return SNMP_ERR_NOERROR;
  879. }                               /* _mfd_ifTable_check_dependencies */
  880. /*----------------------------------------------------------------------
  881.  *
  882.  * SET: Undo setup
  883.  *
  884.  *---------------------------------------------------------------------*/
  885. /*
  886.  * @internal
  887.  * Set the value for a particular column
  888.  */
  889. NETSNMP_STATIC_INLINE int
  890. _ifTable_undo_setup_column(ifTable_rowreq_ctx * rowreq_ctx, int column)
  891. {
  892.     int             rc = SNMPERR_SUCCESS;
  893.     DEBUGMSGTL(("internal:ifTable:_ifTable_undo_setup_column",
  894.                 "calledn"));
  895.     netsnmp_assert(NULL != rowreq_ctx);
  896.     switch (column) {
  897.         /*
  898.          * ifAdminStatus(7)/INTEGER/ASN_INTEGER/long(u_long)//l/A/W/E/r/d/h 
  899.          */
  900.     case COLUMN_IFADMINSTATUS:
  901.         rowreq_ctx->column_set_flags |= FLAG_IFADMINSTATUS;
  902.         rc = ifAdminStatus_undo_setup(rowreq_ctx);
  903.         break;
  904.     default:
  905.         snmp_log(LOG_ERR,
  906.                  "unknown column %d in _ifTable_undo_setup_columnn",
  907.                  column);
  908.         break;
  909.     }
  910.     return rc;
  911. }                               /* _ifTable_undo_setup_column */
  912. /**
  913.  * @internal
  914.  * undo setup
  915.  */
  916. int
  917. _mfd_ifTable_undo_setup(netsnmp_mib_handler *handler,
  918.                         netsnmp_handler_registration *reginfo,
  919.                         netsnmp_agent_request_info *agtreq_info,
  920.                         netsnmp_request_info *requests)
  921. {
  922.     int             rc;
  923.     ifTable_rowreq_ctx *rowreq_ctx =
  924.         netsnmp_container_table_row_extract(requests);
  925.     DEBUGMSGTL(("internal:ifTable:_mfd_ifTable_undo_setup", "calledn"));
  926.     netsnmp_assert(NULL != rowreq_ctx);
  927.     /*
  928.      * allocate undo context
  929.      */
  930.     rowreq_ctx->undo = ifTable_allocate_data();
  931.     if (NULL == rowreq_ctx->undo) {
  932.         /** msg already logged */
  933.         netsnmp_request_set_error_all(requests,
  934.                                       SNMP_ERR_RESOURCEUNAVAILABLE);
  935.         return SNMP_ERR_NOERROR;
  936.     }
  937.     /*
  938.      * row undo setup
  939.      */
  940.     rowreq_ctx->column_set_flags = 0;
  941.     rc = ifTable_undo_setup(rowreq_ctx);
  942.     if (MFD_SUCCESS != rc) {
  943.         DEBUGMSGTL(("verbose:ifTable:mfd", "error %d from "
  944.                     "ifTable_undo_setupn", rc));
  945.         netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
  946.     } else {
  947.         /*
  948.          * column undo setup
  949.          */
  950.         netsnmp_table_request_info *tri;
  951.         for (; requests; requests = requests->next) {
  952.             /*
  953.              * set column data
  954.              */
  955.             tri = netsnmp_extract_table_info(requests);
  956.             if (NULL == tri)
  957.                 continue;
  958.             rc = _ifTable_undo_setup_column(rowreq_ctx, tri->colnum);
  959.             if (MFD_SUCCESS != rc) {
  960.                 DEBUGMSGTL(("verbose:ifTable:mfd", "error %d from "
  961.                             "ifTable_undo_setup_columnn", rc));
  962.                 netsnmp_set_request_error(agtreq_info, requests,
  963.                                           SNMP_VALIDATE_ERR(rc));
  964.             }
  965.         }                       /* for results */
  966.     }
  967.     return SNMP_ERR_NOERROR;
  968. }                               /* _mfd_ifTable_undo_setup */
  969. /**
  970.  * @internal
  971.  * undo setup
  972.  */
  973. int
  974. _mfd_ifTable_undo_cleanup(netsnmp_mib_handler *handler,
  975.                           netsnmp_handler_registration *reginfo,
  976.                           netsnmp_agent_request_info *agtreq_info,
  977.                           netsnmp_request_info *requests)
  978. {
  979.     ifTable_rowreq_ctx *rowreq_ctx =
  980.         netsnmp_container_table_row_extract(requests);
  981.     int             rc;
  982.     DEBUGMSGTL(("internal:ifTable:_mfd_ifTable_undo_cleanup", "calledn"));
  983.     /*
  984.      * failed row create in early stages has no rowreq_ctx
  985.      */
  986.     if (NULL == rowreq_ctx)
  987.         return MFD_SUCCESS;
  988.     /*
  989.      * call user cleanup
  990.      */
  991.     rc = ifTable_undo_cleanup(rowreq_ctx);
  992.     if (MFD_SUCCESS != rc) {
  993.         /*
  994.          * nothing we can do about it but log it
  995.          */
  996.         DEBUGMSGTL(("verbose:ifTable:mfd", "error %d from "
  997.                     "ifTable_undo_cleanupn", rc));
  998.     }
  999.     /*
  1000.      * release undo context, if needed
  1001.      */
  1002.     if (rowreq_ctx->undo) {
  1003.         ifTable_release_data(rowreq_ctx->undo);
  1004.         rowreq_ctx->undo = NULL;
  1005.     }
  1006.     /*
  1007.      * clear set flags
  1008.      */
  1009.     rowreq_ctx->column_set_flags = 0;
  1010.     return SNMP_ERR_NOERROR;
  1011. }                               /* _mfd_ifTable_undo_cleanup */
  1012. /*----------------------------------------------------------------------
  1013.  *
  1014.  * SET: Set values
  1015.  *
  1016.  *---------------------------------------------------------------------*/
  1017. /*
  1018.  * @internal
  1019.  * Set the value for a particular column
  1020.  */
  1021. NETSNMP_STATIC_INLINE int
  1022. _ifTable_set_column(ifTable_rowreq_ctx * rowreq_ctx,
  1023.                     netsnmp_variable_list * var, int column)
  1024. {
  1025.     int             rc = SNMPERR_SUCCESS;
  1026.     DEBUGMSGTL(("internal:ifTable:_ifTable_set_column", "calledn"));
  1027.     netsnmp_assert(NULL != rowreq_ctx);
  1028.     switch (column) {
  1029.         /*
  1030.          * ifAdminStatus(7)/INTEGER/ASN_INTEGER/long(u_long)//l/A/W/E/r/d/h 
  1031.          */
  1032.     case COLUMN_IFADMINSTATUS:
  1033.         if (var->val_len != sizeof(u_long)) {
  1034.             rc = SNMP_ERR_WRONGLENGTH;
  1035.             snmp_log(LOG_ERR,
  1036.                      "varbind size of %d does not match expected size %dn",
  1037.                      var->val_len, sizeof(u_long));
  1038.             break;
  1039.         }
  1040.         rowreq_ctx->column_set_flags |= FLAG_IFADMINSTATUS;
  1041.         rc = ifAdminStatus_set(rowreq_ctx, *((u_long *) var->val.string));
  1042.         break;
  1043.     default:
  1044.         snmp_log(LOG_ERR, "unknown column %d in _ifTable_set_columnn",
  1045.                  column);
  1046.         break;
  1047.     }
  1048.     return rc;
  1049. }                               /* _ifTable_set_column */
  1050. int
  1051. _mfd_ifTable_set_values(netsnmp_mib_handler *handler,
  1052.                         netsnmp_handler_registration *reginfo,
  1053.                         netsnmp_agent_request_info *agtreq_info,
  1054.                         netsnmp_request_info *requests)
  1055. {
  1056.     ifTable_rowreq_ctx *rowreq_ctx =
  1057.         netsnmp_container_table_row_extract(requests);
  1058.     netsnmp_table_request_info *tri;
  1059.     int             rc = SNMP_ERR_NOERROR;
  1060.     DEBUGMSGTL(("internal:ifTable:_mfd_ifTable_set_values", "calledn"));
  1061.     netsnmp_assert(NULL != rowreq_ctx);
  1062.     rowreq_ctx->column_set_flags = 0;
  1063.     for (; requests; requests = requests->next) {
  1064.         /*
  1065.          * set column data
  1066.          */
  1067.         tri = netsnmp_extract_table_info(requests);
  1068.         if (NULL == tri)
  1069.             continue;
  1070.         rc = _ifTable_set_column(rowreq_ctx,
  1071.                                  requests->requestvb, tri->colnum);
  1072.         if (MFD_SUCCESS != rc) {
  1073.             DEBUGMSGTL(("verbose:ifTable:mfd", "error %d from "
  1074.                         "ifTable_set_columnn", rc));
  1075.             netsnmp_set_request_error(agtreq_info, requests,
  1076.                                       SNMP_VALIDATE_ERR(rc));
  1077.         }
  1078.     }                           /* for results */
  1079.     return SNMP_ERR_NOERROR;
  1080. }                               /* _mfd_ifTable_set_values */
  1081. /*----------------------------------------------------------------------
  1082.  *
  1083.  * SET: commit
  1084.  *
  1085.  *---------------------------------------------------------------------*/
  1086. /**
  1087.  * @internal
  1088.  * commit the values
  1089.  */
  1090. int
  1091. _mfd_ifTable_commit(netsnmp_mib_handler *handler,
  1092.                     netsnmp_handler_registration *reginfo,
  1093.                     netsnmp_agent_request_info *agtreq_info,
  1094.                     netsnmp_request_info *requests)
  1095. {
  1096.     int             rc;
  1097.     ifTable_rowreq_ctx *rowreq_ctx =
  1098.         netsnmp_container_table_row_extract(requests);
  1099.     DEBUGMSGTL(("internal:ifTable:_mfd_ifTable_commit", "calledn"));
  1100.     netsnmp_assert(NULL != rowreq_ctx);
  1101.     rc = ifTable_commit(rowreq_ctx);
  1102.     if (MFD_SUCCESS != rc) {
  1103.         DEBUGMSGTL(("verbose:ifTable:mfd", "error %d from "
  1104.                     "ifTable_commitn", rc));
  1105.         netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
  1106.     }
  1107.     return SNMP_ERR_NOERROR;
  1108. }
  1109. int
  1110. _mfd_ifTable_undo_commit(netsnmp_mib_handler *handler,
  1111.                          netsnmp_handler_registration *reginfo,
  1112.                          netsnmp_agent_request_info *agtreq_info,
  1113.                          netsnmp_request_info *requests)
  1114. {
  1115.     int             rc;
  1116.     ifTable_rowreq_ctx *rowreq_ctx =
  1117.         netsnmp_container_table_row_extract(requests);
  1118.     DEBUGMSGTL(("internal:ifTable:_mfd_ifTable_undo_commit", "calledn"));
  1119.     netsnmp_assert(NULL != rowreq_ctx);
  1120.     rc = ifTable_undo_commit(rowreq_ctx);
  1121.     if (MFD_SUCCESS != rc) {
  1122.         /*
  1123.          * nothing we can do about it but log it
  1124.          */
  1125.         DEBUGMSGTL(("verbose:ifTable:mfd", "error %d from "
  1126.                     "ifTable_undo_commitn", rc));
  1127.     }
  1128.     return SNMP_ERR_NOERROR;
  1129. }                               /* _mfd_ifTable_commit */
  1130. /*----------------------------------------------------------------------
  1131.  *
  1132.  * SET: Undo
  1133.  *
  1134.  *---------------------------------------------------------------------*/
  1135. /**
  1136.  * @internal
  1137.  * undo the value for a particular column
  1138.  */
  1139. NETSNMP_STATIC_INLINE int
  1140. _ifTable_undo_column(ifTable_rowreq_ctx * rowreq_ctx,
  1141.                      netsnmp_variable_list * var, int column)
  1142. {
  1143.     int             rc = SNMPERR_SUCCESS;
  1144.     DEBUGMSGTL(("internal:ifTable:_ifTable_undo_column", "calledn"));
  1145.     netsnmp_assert(NULL != rowreq_ctx);
  1146.     switch (column) {
  1147.         /*
  1148.          * ifAdminStatus(7)/INTEGER/ASN_INTEGER/long(u_long)//l/A/W/E/r/d/h 
  1149.          */
  1150.     case COLUMN_IFADMINSTATUS:
  1151.         rc = ifAdminStatus_undo(rowreq_ctx);
  1152.         break;
  1153.     default:
  1154.         snmp_log(LOG_ERR, "unknown column %d in _ifTable_undo_columnn",
  1155.                  column);
  1156.         break;
  1157.     }
  1158.     return rc;
  1159. }                               /* _ifTable_undo_column */
  1160. int
  1161. _mfd_ifTable_undo_values(netsnmp_mib_handler *handler,
  1162.                          netsnmp_handler_registration *reginfo,
  1163.                          netsnmp_agent_request_info *agtreq_info,
  1164.                          netsnmp_request_info *requests)
  1165. {
  1166.     int             rc;
  1167.     ifTable_rowreq_ctx *rowreq_ctx =
  1168.         netsnmp_container_table_row_extract(requests);
  1169.     netsnmp_table_request_info *tri;
  1170.     DEBUGMSGTL(("internal:ifTable:_mfd_ifTable_undo_values", "calledn"));
  1171.     netsnmp_assert(NULL != rowreq_ctx);
  1172.     for (; requests; requests = requests->next) {
  1173.         /*
  1174.          * set column data
  1175.          */
  1176.         tri = netsnmp_extract_table_info(requests);
  1177.         if (NULL == tri)
  1178.             continue;
  1179.         rc = _ifTable_undo_column(rowreq_ctx, requests->requestvb,
  1180.                                   tri->colnum);
  1181.         if (MFD_SUCCESS != rc) {
  1182.             /*
  1183.              * nothing we can do about it but log it
  1184.              */
  1185.             DEBUGMSGTL(("verbose:ifTable:mfd", "error %d from "
  1186.                         "ifTable_undo_columnn", rc));
  1187.         }
  1188.     }                           /* for results */
  1189.     return SNMP_ERR_NOERROR;
  1190. }                               /* _mfd_ifTable_undo_values */
  1191. /***********************************************************************
  1192.  *
  1193.  * DATA ACCESS
  1194.  *
  1195.  ***********************************************************************/
  1196. /**
  1197.  * @internal
  1198.  */
  1199. static int
  1200. _cache_load(netsnmp_cache * cache, void *vmagic)
  1201. {
  1202.     DEBUGMSGTL(("internal:ifTable:_cache_load", "calledn"));
  1203.     if ((NULL == cache) || (NULL == cache->magic)) {
  1204.         snmp_log(LOG_ERR, "invalid cache for ifTable_cache_loadn");
  1205.         return -1;
  1206.     }
  1207.     /** should only be called for an invalid or expired cache */
  1208.     netsnmp_assert((0 == cache->valid) || (1 == cache->expired));
  1209.     /*
  1210.      * call user code
  1211.      */
  1212.     return ifTable_cache_load((netsnmp_container *) cache->magic);
  1213. }                               /* _cache_load */
  1214. /**
  1215.  * @internal
  1216.  */
  1217. static void
  1218. _cache_item_free(ifTable_rowreq_ctx * rowreq_ctx, void *context)
  1219. {
  1220.     DEBUGMSGTL(("internal:ifTable:_cache_item_free", "calledn"));
  1221.     if (NULL == rowreq_ctx)
  1222.         return;
  1223.     ifTable_release_rowreq_ctx(rowreq_ctx);
  1224. }                               /* _cache_item_free */
  1225. /**
  1226.  * @internal
  1227.  */
  1228. static void
  1229. _cache_free(netsnmp_cache * cache, void *magic)
  1230. {
  1231.     netsnmp_container *container;
  1232.     DEBUGMSGTL(("internal:ifTable:_cache_free", "calledn"));
  1233.     if ((NULL == cache) || (NULL == cache->magic)) {
  1234.         snmp_log(LOG_ERR, "invalid cache in ifTable_cache_freen");
  1235.         return;
  1236.     }
  1237.     container = (netsnmp_container *) cache->magic;
  1238.     /*
  1239.      * call user code
  1240.      */
  1241.     ifTable_cache_free(container);
  1242.     /*
  1243.      * free all items. inefficient, but easy.
  1244.      */
  1245.     CONTAINER_CLEAR(container,
  1246.                     (netsnmp_container_obj_func *) _cache_item_free, NULL);
  1247. }                               /* _cache_free */
  1248. /**
  1249.  * @internal
  1250.  * initialize the iterator container with functions or wrappers
  1251.  */
  1252. void
  1253. _ifTable_container_init(ifTable_interface_ctx * if_ctx)
  1254. {
  1255.     DEBUGMSGTL(("internal:ifTable:_ifTable_container_init", "calledn"));
  1256.     /*
  1257.      * set up the cache
  1258.      */
  1259.     if_ctx->cache = netsnmp_cache_create(30,    /* timeout in seconds */
  1260.                                          _cache_load, _cache_free,
  1261.                                          ifTable_oid, ifTable_oid_size);
  1262.     if (NULL == if_ctx->cache) {
  1263.         snmp_log(LOG_ERR, "error creating cache for ifTablen");
  1264.         return;
  1265.     }
  1266.     if_ctx->cache->flags = NETSNMP_CACHE_DONT_INVALIDATE_ON_SET;
  1267.     ifTable_container_init(&if_ctx->container, if_ctx->cache);
  1268.     if (NULL == if_ctx->container)
  1269.         if_ctx->container =
  1270.             netsnmp_container_find("ifTable:table_container");
  1271.     if (NULL == if_ctx->container) {
  1272.         snmp_log(LOG_ERR, "error creating container in "
  1273.                  "ifTable_container_initn");
  1274.         return;
  1275.     }
  1276.     if_ctx->cache->magic = (void *) if_ctx->container;
  1277. }                               /* _ifTable_container_init */