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

SNMP编程

开发平台:

Unix_Linux

  1. /**************************************************************
  2.  * Copyright (C) 2001 Alex Rozin, Optical Access 
  3.  *
  4.  *                     All Rights Reserved
  5.  *
  6.  * Permission to use, copy, modify and distribute this software and its
  7.  * documentation for any purpose and without fee is hereby granted,
  8.  * provided that the above copyright notice appear in all copies and that
  9.  * both that copyright notice and this permission notice appear in
  10.  * supporting documentation.
  11.  * 
  12.  * ALEX ROZIN DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  13.  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  14.  * ALEX ROZIN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  15.  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  16.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  17.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  18.  * SOFTWARE.
  19.  ******************************************************************/
  20. #include <net-snmp/net-snmp-config.h>
  21. #if HAVE_STDLIB_H
  22. #include <stdlib.h>
  23. #endif
  24. #if TIME_WITH_SYS_TIME
  25. # ifdef WIN32
  26. #  include <sys/timeb.h>
  27. # else
  28. #  include <sys/time.h>
  29. # endif
  30. # include <time.h>
  31. #else
  32. # if HAVE_SYS_TIME_H
  33. #  include <sys/time.h>
  34. # else
  35. #  include <time.h>
  36. # endif
  37. #endif
  38. #if HAVE_UNISTD_H
  39. #include <unistd.h>
  40. #endif
  41. #include <net-snmp/net-snmp-includes.h>
  42. #include <net-snmp/agent/net-snmp-agent-includes.h>
  43. #include "util_funcs.h"
  44. #include "history.h"
  45. /*
  46.  * Implementation headers 
  47.  */
  48. #include "agutil_api.h"
  49. #include "row_api.h"
  50. /*
  51.  * File scope definitions section 
  52.  */
  53. #define historyControlEntryFirstIndexBegin      11
  54. #define CTRL_INDEX 3
  55. #define CTRL_DATASOURCE 4
  56. #define CTRL_BUCKETSREQUESTED 5
  57. #define CTRL_BUCKETSGRANTED 6
  58. #define CTRL_INTERVAL 7
  59. #define CTRL_OWNER 8
  60. #define CTRL_STATUS 9
  61. #define DATA_INDEX 3
  62. #define DATA_SAMPLEINDEX 4
  63. #define DATA_INTERVALSTART 5
  64. #define DATA_DROPEVENTS 6
  65. #define DATA_OCTETS 7
  66. #define DATA_PKTS 8
  67. #define DATA_BROADCASTPKTS 9
  68. #define DATA_MULTICASTPKTS 10
  69. #define DATA_CRCALIGNERRORS 11
  70. #define DATA_UNDERSIZEPKTS 12
  71. #define DATA_OVERSIZEPKTS 13
  72. #define DATA_FRAGMENTS 14
  73. #define DATA_JABBERS 15
  74. #define DATA_COLLISIONS 16
  75. #define DATA_UTILIZATION 17
  76. /*
  77.  * defaults & limitations 
  78.  */
  79. #define MAX_BUCKETS_IN_CRTL_ENTRY 50
  80. #define HIST_DEF_BUCK_REQ 50
  81. #define HIST_DEF_INTERVAL 1800
  82. static VAR_OID_T DEFAULT_DATA_SOURCE = { 11,    /* ifIndex.1 */
  83.     {1, 3, 6, 1, 2, 1, 2, 2, 1, 1, 1}
  84. };
  85. typedef struct data_struct_t {
  86.     struct data_struct_t *next;
  87.     u_long          data_index;
  88.     u_long          start_interval;
  89.     u_long          utilization;
  90.     ETH_STATS_T     EthData;
  91. } DATA_ENTRY_T;
  92. typedef struct {
  93.     u_long          interval;
  94.     u_long          timer_id;
  95.     VAR_OID_T       data_source;
  96.     u_long          coeff;
  97.     DATA_ENTRY_T    previous_bucket;
  98.     SCROLLER_T      scrlr;
  99. } CRTL_ENTRY_T;
  100. static TABLE_DEFINTION_T HistoryCtrlTable;
  101. static TABLE_DEFINTION_T *table_ptr = &HistoryCtrlTable;
  102. /*
  103.  * Main section 
  104.  */
  105. #  define Leaf_historyControlDataSource                    2
  106. #  define Leaf_historyControlBucketsRequested              3
  107. #  define Leaf_historyControlInterval                      5
  108. #  define Leaf_historyControlOwner                         6
  109. #  define Leaf_historyControlStatus                        7
  110. #  define MIN_historyControlBucketsRequested               1
  111. #  define MAX_historyControlBucketsRequested               65535
  112. #  define MIN_historyControlInterval                       1
  113. #  define MAX_historyControlInterval                       3600
  114. static int
  115. write_historyControl(int action, u_char * var_val, u_char var_val_type,
  116.                      size_t var_val_len, u_char * statP,
  117.                      oid * name, size_t name_len)
  118. {
  119.     long            long_temp;
  120.     int             leaf_id, snmp_status;
  121.     static int      prev_action = COMMIT;
  122.     RMON_ENTRY_T   *hdr;
  123.     CRTL_ENTRY_T   *cloned_body;
  124.     CRTL_ENTRY_T   *body;
  125.     switch (action) {
  126.     case RESERVE1:
  127.     case FREE:
  128.     case UNDO:
  129.     case ACTION:
  130.     case COMMIT:
  131.     default:
  132.         return ROWAPI_do_another_action(name,
  133.                                         historyControlEntryFirstIndexBegin,
  134.                                         action, &prev_action, table_ptr,
  135.                                         sizeof(CRTL_ENTRY_T));
  136.     case RESERVE2:
  137.         /*
  138.          * get values from PDU, check them and save them in the cloned entry 
  139.          */
  140.         long_temp = name[historyControlEntryFirstIndexBegin];
  141.         leaf_id = (int) name[historyControlEntryFirstIndexBegin - 1];
  142.         hdr = ROWAPI_find(table_ptr, long_temp);        /* it MUST be OK */
  143.         cloned_body = (CRTL_ENTRY_T *) hdr->tmp;
  144.         body = (CRTL_ENTRY_T *) hdr->body;
  145.         switch (leaf_id) {
  146.         case Leaf_historyControlDataSource:
  147.             snmp_status = AGUTIL_get_oid_value(var_val, var_val_type,
  148.                                                var_val_len,
  149.                                                &cloned_body->data_source);
  150.             if (SNMP_ERR_NOERROR != snmp_status) {
  151.                 ag_trace("can't browse historyControlDataSource");
  152.                 return snmp_status;
  153.             }
  154.             if (RMON1_ENTRY_UNDER_CREATION != hdr->status &&
  155.                 snmp_oid_compare(cloned_body->data_source.objid,
  156.                                  cloned_body->data_source.length,
  157.                                  body->data_source.objid,
  158.                                  body->data_source.length)) {
  159.                 ag_trace
  160.                     ("can't change historyControlDataSource - not Creation");
  161.                 return SNMP_ERR_BADVALUE;
  162.             }
  163.             break;
  164.         case Leaf_historyControlBucketsRequested:
  165.             snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
  166.                                                var_val_len,
  167.                                                MIN_historyControlBucketsRequested,
  168.                                                MAX_historyControlBucketsRequested,
  169.                                                &cloned_body->scrlr.
  170.                                                data_requested);
  171.             if (SNMP_ERR_NOERROR != snmp_status) {
  172.                 return snmp_status;
  173.             }
  174. #if 0
  175.             if (RMON1_ENTRY_UNDER_CREATION != hdr->status &&
  176.                 cloned_body->scrlr.data_requested !=
  177.                 body->scrlr.data_requested)
  178.                 return SNMP_ERR_BADVALUE;
  179. #endif
  180.             break;
  181.         case Leaf_historyControlInterval:
  182.             snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
  183.                                                var_val_len,
  184.                                                MIN_historyControlInterval,
  185.                                                MAX_historyControlInterval,
  186.                                                &cloned_body->interval);
  187.             if (SNMP_ERR_NOERROR != snmp_status) {
  188.                 return snmp_status;
  189.             }
  190. #if 0
  191.             if (RMON1_ENTRY_UNDER_CREATION != hdr->status &&
  192.                 cloned_body->interval != body->interval)
  193.                 return SNMP_ERR_BADVALUE;
  194. #endif
  195.             break;
  196.         case Leaf_historyControlOwner:
  197.             if (hdr->new_owner)
  198.                 AGFREE(hdr->new_owner);
  199.             hdr->new_owner = AGMALLOC(MAX_OWNERSTRING);;
  200.             if (!hdr->new_owner)
  201.                 return SNMP_ERR_TOOBIG;
  202.             snmp_status = AGUTIL_get_string_value(var_val, var_val_type,
  203.                                                   var_val_len,
  204.                                                   MAX_OWNERSTRING,
  205.                                                   1, NULL, hdr->new_owner);
  206.             if (SNMP_ERR_NOERROR != snmp_status) {
  207.                 return snmp_status;
  208.             }
  209.             break;
  210.         case Leaf_historyControlStatus:
  211.             snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
  212.                                                var_val_len,
  213.                                                RMON1_ENTRY_VALID,
  214.                                                RMON1_ENTRY_INVALID,
  215.                                                &long_temp);
  216.             if (SNMP_ERR_NOERROR != snmp_status) {
  217.                 return snmp_status;
  218.             }
  219.             hdr->new_status = long_temp;
  220.             break;
  221.         default:
  222.             ag_trace("%s:unknown leaf_id=%dn", table_ptr->name,
  223.                      (int) leaf_id);
  224.             return SNMP_ERR_NOSUCHNAME;
  225.         }                       /* of switch by 'leaf_id' */
  226.         break;
  227.     }                           /* of switch by actions */
  228.     prev_action = action;
  229.     return SNMP_ERR_NOERROR;
  230. }
  231. /*
  232.  * var_historyControlTable():
  233.  */
  234. unsigned char  *
  235. var_historyControlTable(struct variable *vp,
  236.                         oid * name,
  237.                         size_t * length,
  238.                         int exact,
  239.                         size_t * var_len, WriteMethod ** write_method)
  240. {
  241.     static long     long_ret;
  242.     static CRTL_ENTRY_T theEntry;
  243.     RMON_ENTRY_T   *hdr;
  244.     *write_method = write_historyControl;
  245.     hdr = ROWAPI_header_ControlEntry(vp, name, length, exact, var_len,
  246.                                      table_ptr,
  247.                                      &theEntry, sizeof(CRTL_ENTRY_T));
  248.     if (!hdr)
  249.         return NULL;
  250.     *var_len = sizeof(long);    /* default */
  251.     switch (vp->magic) {
  252.     case CTRL_INDEX:
  253.         long_ret = hdr->ctrl_index;
  254.         return (unsigned char *) &long_ret;
  255.     case CTRL_DATASOURCE:
  256.         *var_len = sizeof(oid) * theEntry.data_source.length;
  257.         return (unsigned char *) theEntry.data_source.objid;
  258.     case CTRL_BUCKETSREQUESTED:
  259.         long_ret = theEntry.scrlr.data_requested;
  260.         return (unsigned char *) &long_ret;
  261.     case CTRL_BUCKETSGRANTED:
  262.         long_ret = theEntry.scrlr.data_granted;
  263.         return (unsigned char *) &long_ret;
  264.     case CTRL_INTERVAL:
  265.         long_ret = theEntry.interval;
  266.         return (unsigned char *) &long_ret;
  267.     case CTRL_OWNER:
  268.         if (hdr->owner) {
  269.             *var_len = strlen(hdr->owner);
  270.             return (unsigned char *) hdr->owner;
  271.         } else {
  272.             *var_len = 0;
  273.             return (unsigned char *) "";
  274.         }
  275.     case CTRL_STATUS:
  276.         long_ret = hdr->status;
  277.         return (unsigned char *) &long_ret;
  278.     default:
  279.         ag_trace("HistoryControlTable: unknown vp->magic=%d",
  280.                  (int) vp->magic);
  281.         ERROR_MSG("");
  282.     }
  283.     return NULL;
  284. }
  285. /*
  286.  * history row management control callbacks 
  287.  */
  288. static void
  289. compute_delta(ETH_STATS_T * delta,
  290.               ETH_STATS_T * newval, ETH_STATS_T * prevval)
  291. {
  292. #define CNT_DIF(X) delta->X = newval->X - prevval->X
  293.     CNT_DIF(octets);
  294.     CNT_DIF(packets);
  295.     CNT_DIF(bcast_pkts);
  296.     CNT_DIF(mcast_pkts);
  297.     CNT_DIF(crc_align);
  298.     CNT_DIF(undersize);
  299.     CNT_DIF(oversize);
  300.     CNT_DIF(fragments);
  301.     CNT_DIF(jabbers);
  302.     CNT_DIF(collisions);
  303. }
  304. static void
  305. history_get_backet(unsigned int clientreg, void *clientarg)
  306. {
  307.     RMON_ENTRY_T   *hdr_ptr;
  308.     CRTL_ENTRY_T   *body;
  309.     DATA_ENTRY_T   *bptr;
  310.     ETH_STATS_T     newSample;
  311.     /*
  312.      * ag_trace ("history_get_backet: timer_id=%d", (int) clientreg); 
  313.      */
  314.     hdr_ptr = (RMON_ENTRY_T *) clientarg;
  315.     if (!hdr_ptr) {
  316.         ag_trace
  317.             ("Err: history_get_backet: hdr_ptr=NULL ? (Inserted in shock)");
  318.         return;
  319.     }
  320.     body = (CRTL_ENTRY_T *) hdr_ptr->body;
  321.     if (!body) {
  322.         ag_trace
  323.             ("Err: history_get_backet: body=NULL ? (Inserted in shock)");
  324.         return;
  325.     }
  326.     if (RMON1_ENTRY_VALID != hdr_ptr->status) {
  327.         ag_trace("Err: history_get_backet when entry %d is not valid ?!!",
  328.                  (int) hdr_ptr->ctrl_index);
  329.         /*
  330.          * snmp_alarm_print_list (); 
  331.          */
  332.         snmp_alarm_unregister(body->timer_id);
  333.         ag_trace("Err: unregistered %ld", (long) body->timer_id);
  334.         return;
  335.     }
  336.     SYSTEM_get_eth_statistics(&body->data_source, &newSample);
  337.     bptr = ROWDATAAPI_locate_new_data(&body->scrlr);
  338.     if (!bptr) {
  339.         ag_trace
  340.             ("Err: history_get_backet for %d: empty bucket's list !??n",
  341.              (int) hdr_ptr->ctrl_index);
  342.         return;
  343.     }
  344.     bptr->data_index = ROWDATAAPI_get_total_number(&body->scrlr);
  345.     bptr->start_interval = body->previous_bucket.start_interval;
  346.     compute_delta(&bptr->EthData, &newSample,
  347.                   &body->previous_bucket.EthData);
  348.     bptr->utilization =
  349.         bptr->EthData.octets * 8 + bptr->EthData.packets * (96 + 64);
  350.     bptr->utilization /= body->coeff;
  351.     /*
  352.      * update previous_bucket 
  353.      */
  354.     body->previous_bucket.start_interval = AGUTIL_sys_up_time();
  355.     memcpy(&body->previous_bucket.EthData, &newSample,
  356.            sizeof(ETH_STATS_T));
  357. }
  358. /*
  359.  * Control Table RowApi Callbacks 
  360.  */
  361. int
  362. history_Create(RMON_ENTRY_T * eptr)
  363. {                               /* create the body: alloc it and set defaults */
  364.     CRTL_ENTRY_T   *body;
  365.     eptr->body = AGMALLOC(sizeof(CRTL_ENTRY_T));
  366.     if (!eptr->body)
  367.         return -3;
  368.     body = (CRTL_ENTRY_T *) eptr->body;
  369.     /*
  370.      * set defaults 
  371.      */
  372.     body->interval = HIST_DEF_INTERVAL;
  373.     body->timer_id = 0;
  374.     memcpy(&body->data_source, &DEFAULT_DATA_SOURCE, sizeof(VAR_OID_T));
  375.     ROWDATAAPI_init(&body->scrlr, HIST_DEF_BUCK_REQ,
  376.                     MAX_BUCKETS_IN_CRTL_ENTRY, sizeof(DATA_ENTRY_T), NULL);
  377.     return 0;
  378. }
  379. int
  380. history_Validate(RMON_ENTRY_T * eptr)
  381. {
  382.     /*
  383.      * T.B.D. (system dependent) check valid inteface in body->data_source; 
  384.      */
  385.     return 0;
  386. }
  387. int
  388. history_Activate(RMON_ENTRY_T * eptr)
  389. {
  390.     CRTL_ENTRY_T   *body = (CRTL_ENTRY_T *) eptr->body;
  391.     body->coeff = 100000L * (long) body->interval;
  392.     ROWDATAAPI_set_size(&body->scrlr,
  393.                         body->scrlr.data_requested,
  394.                         (u_char)(RMON1_ENTRY_VALID == eptr->status) );
  395.     SYSTEM_get_eth_statistics(&body->data_source,
  396.                               &body->previous_bucket.EthData);
  397.     body->previous_bucket.start_interval = AGUTIL_sys_up_time();
  398.     body->scrlr.current_data_ptr = body->scrlr.first_data_ptr;
  399.     /*
  400.      * ag_trace ("Dbg:   registered in history_Activate"); 
  401.      */
  402.     body->timer_id = snmp_alarm_register(body->interval, SA_REPEAT,
  403.                                          history_get_backet, eptr);
  404.     return 0;
  405. }
  406. int
  407. history_Deactivate(RMON_ENTRY_T * eptr)
  408. {
  409.     CRTL_ENTRY_T   *body = (CRTL_ENTRY_T *) eptr->body;
  410.     snmp_alarm_unregister(body->timer_id);
  411.     /*
  412.      * ag_trace ("Dbg: unregistered in history_Deactivate timer_id=%d",
  413.      * (int) body->timer_id); 
  414.      */
  415.     /*
  416.      * free data list 
  417.      */
  418.     ROWDATAAPI_descructor(&body->scrlr);
  419.     return 0;
  420. }
  421. int
  422. history_Copy(RMON_ENTRY_T * eptr)
  423. {
  424.     CRTL_ENTRY_T   *body = (CRTL_ENTRY_T *) eptr->body;
  425.     CRTL_ENTRY_T   *clone = (CRTL_ENTRY_T *) eptr->tmp;
  426.     if (body->scrlr.data_requested != clone->scrlr.data_requested) {
  427.         ROWDATAAPI_set_size(&body->scrlr, clone->scrlr.data_requested,
  428.                             (u_char)(RMON1_ENTRY_VALID == eptr->status) );
  429.     }
  430.     if (body->interval != clone->interval) {
  431.         if (RMON1_ENTRY_VALID == eptr->status) {
  432.             snmp_alarm_unregister(body->timer_id);
  433.             body->timer_id =
  434.                 snmp_alarm_register(clone->interval, SA_REPEAT,
  435.                                     history_get_backet, eptr);
  436.         }
  437.         body->interval = clone->interval;
  438.     }
  439.     if (snmp_oid_compare
  440.         (clone->data_source.objid, clone->data_source.length,
  441.          body->data_source.objid, body->data_source.length)) {
  442.         memcpy(&body->data_source, &clone->data_source, sizeof(VAR_OID_T));
  443.     }
  444.     return 0;
  445. }
  446. static SCROLLER_T *
  447. history_extract_scroller(void *v_body)
  448. {
  449.     CRTL_ENTRY_T   *body = (CRTL_ENTRY_T *) v_body;
  450.     return &body->scrlr;
  451. }
  452. /*
  453.  * var_etherHistoryTable():
  454.  */
  455. unsigned char  *
  456. var_etherHistoryTable(struct variable *vp,
  457.                       oid * name,
  458.                       size_t * length,
  459.                       int exact,
  460.                       size_t * var_len, WriteMethod ** write_method)
  461. {
  462.     static long     long_ret;
  463.     static DATA_ENTRY_T theBucket;
  464.     RMON_ENTRY_T   *hdr;
  465.     CRTL_ENTRY_T   *ctrl;
  466.     *write_method = NULL;
  467.     hdr = ROWDATAAPI_header_DataEntry(vp, name, length, exact, var_len,
  468.                                       table_ptr,
  469.                                       &history_extract_scroller,
  470.                                       sizeof(DATA_ENTRY_T), &theBucket);
  471.     if (!hdr)
  472.         return NULL;
  473.     *var_len = sizeof(long);    /* default */
  474.     ctrl = (CRTL_ENTRY_T *) hdr->body;
  475.     switch (vp->magic) {
  476.     case DATA_INDEX:
  477.         long_ret = hdr->ctrl_index;
  478.         return (unsigned char *) &long_ret;
  479.     case DATA_SAMPLEINDEX:
  480.         long_ret = theBucket.data_index;
  481.         return (unsigned char *) &long_ret;
  482.     case DATA_INTERVALSTART:
  483.         long_ret = 0;
  484.         return (unsigned char *) &theBucket.start_interval;
  485.     case DATA_DROPEVENTS:
  486.         long_ret = 0;
  487.         return (unsigned char *) &long_ret;
  488.     case DATA_OCTETS:
  489.         long_ret = 0;
  490.         return (unsigned char *) &theBucket.EthData.octets;
  491.     case DATA_PKTS:
  492.         long_ret = 0;
  493.         return (unsigned char *) &theBucket.EthData.packets;
  494.     case DATA_BROADCASTPKTS:
  495.         long_ret = 0;
  496.         return (unsigned char *) &theBucket.EthData.bcast_pkts;
  497.     case DATA_MULTICASTPKTS:
  498.         long_ret = 0;
  499.         return (unsigned char *) &theBucket.EthData.mcast_pkts;
  500.     case DATA_CRCALIGNERRORS:
  501.         long_ret = 0;
  502.         return (unsigned char *) &theBucket.EthData.crc_align;
  503.     case DATA_UNDERSIZEPKTS:
  504.         long_ret = 0;
  505.         return (unsigned char *) &theBucket.EthData.undersize;
  506.     case DATA_OVERSIZEPKTS:
  507.         long_ret = 0;
  508.         return (unsigned char *) &theBucket.EthData.oversize;
  509.     case DATA_FRAGMENTS:
  510.         long_ret = 0;
  511.         return (unsigned char *) &theBucket.EthData.fragments;
  512.     case DATA_JABBERS:
  513.         long_ret = 0;
  514.         return (unsigned char *) &theBucket.EthData.jabbers;
  515.     case DATA_COLLISIONS:
  516.         long_ret = 0;
  517.         return (unsigned char *) &theBucket.EthData.collisions;
  518.     case DATA_UTILIZATION:
  519.         long_ret = 0;
  520.         return (unsigned char *) &theBucket.utilization;
  521.     default:
  522.         ag_trace("etherHistoryTable: unknown vp->magic=%d",
  523.                  (int) vp->magic);
  524.         ERROR_MSG("");
  525.     }
  526.     return NULL;
  527. }
  528. #if 1                           /* debug, but may be used for init. TBD: may be token snmpd.conf ? */
  529. int
  530. add_hist_entry(int ctrl_index, int ifIndex,
  531.                u_long interval, u_long requested)
  532. {
  533.     register RMON_ENTRY_T *eptr;
  534.     register CRTL_ENTRY_T *body;
  535.     int             ierr;
  536.     ierr = ROWAPI_new(table_ptr, ctrl_index);
  537.     if (ierr) {
  538.         ag_trace("ROWAPI_new failed with %d", ierr);
  539.         return ierr;
  540.     }
  541.     eptr = ROWAPI_find(table_ptr, ctrl_index);
  542.     if (!eptr) {
  543.         ag_trace("ROWAPI_find failed");
  544.         return -4;
  545.     }
  546.     body = (CRTL_ENTRY_T *) eptr->body;
  547.     /*
  548.      * set parameters 
  549.      */
  550.     body->data_source.objid[body->data_source.length - 1] = ifIndex;
  551.     body->interval = interval;
  552.     body->scrlr.data_requested = requested;
  553.     eptr->new_status = RMON1_ENTRY_VALID;
  554.     ierr = ROWAPI_commit(table_ptr, ctrl_index);
  555.     if (ierr) {
  556.         ag_trace("ROWAPI_commit failed with %d", ierr);
  557.     }
  558.     return ierr;
  559. }
  560. #endif
  561. /*
  562.  * Registration & Initializatio section 
  563.  */
  564. oid             historyControlTable_variables_oid[] =
  565.     { 1, 3, 6, 1, 2, 1, 16, 2, 1 };
  566. struct variable2 historyControlTable_variables[] = {
  567.     /*
  568.      * magic number        , variable type, ro/rw , callback fn  ,           L, oidsuffix 
  569.      */
  570.     {CTRL_INDEX, ASN_INTEGER, RONLY, var_historyControlTable, 2, {1, 1}},
  571.     {CTRL_DATASOURCE, ASN_OBJECT_ID, RWRITE, var_historyControlTable, 2,
  572.      {1, 2}},
  573.     {CTRL_BUCKETSREQUESTED, ASN_INTEGER, RWRITE, var_historyControlTable,
  574.      2, {1, 3}},
  575.     {CTRL_BUCKETSGRANTED, ASN_INTEGER, RONLY, var_historyControlTable, 2,
  576.      {1, 4}},
  577.     {CTRL_INTERVAL, ASN_INTEGER, RWRITE, var_historyControlTable, 2,
  578.      {1, 5}},
  579.     {CTRL_OWNER, ASN_OCTET_STR, RWRITE, var_historyControlTable, 2,
  580.      {1, 6}},
  581.     {CTRL_STATUS, ASN_INTEGER, RWRITE, var_historyControlTable, 2, {1, 7}},
  582. };
  583. oid             etherHistoryTable_variables_oid[] =
  584.     { 1, 3, 6, 1, 2, 1, 16, 2, 2 };
  585. struct variable2 etherHistoryTable_variables[] = {
  586.     /*
  587.      * magic number     , variable type , ro/rw , callback fn  ,        L, oidsuffix 
  588.      */
  589.     {DATA_INDEX, ASN_INTEGER, RONLY, var_etherHistoryTable, 2, {1, 1}},
  590.     {DATA_SAMPLEINDEX, ASN_INTEGER, RONLY, var_etherHistoryTable, 2,
  591.      {1, 2}},
  592.     {DATA_INTERVALSTART, ASN_TIMETICKS, RONLY, var_etherHistoryTable, 2,
  593.      {1, 3}},
  594.     {DATA_DROPEVENTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
  595.      {1, 4}},
  596.     {DATA_OCTETS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2, {1, 5}},
  597.     {DATA_PKTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2, {1, 6}},
  598.     {DATA_BROADCASTPKTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
  599.      {1, 7}},
  600.     {DATA_MULTICASTPKTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
  601.      {1, 8}},
  602.     {DATA_CRCALIGNERRORS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
  603.      {1, 9}},
  604.     {DATA_UNDERSIZEPKTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
  605.      {1, 10}},
  606.     {DATA_OVERSIZEPKTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
  607.      {1, 11}},
  608.     {DATA_FRAGMENTS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
  609.      {1, 12}},
  610.     {DATA_JABBERS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2, {1, 13}},
  611.     {DATA_COLLISIONS, ASN_COUNTER, RONLY, var_etherHistoryTable, 2,
  612.      {1, 14}},
  613.     {DATA_UTILIZATION, ASN_INTEGER, RONLY, var_etherHistoryTable, 2,
  614.      {1, 15}},
  615. };
  616. void
  617. init_history(void)
  618. {
  619.     REGISTER_MIB("historyControlTable", historyControlTable_variables,
  620.                  variable2, historyControlTable_variables_oid);
  621.     REGISTER_MIB("etherHistoryTable", etherHistoryTable_variables,
  622.                  variable2, etherHistoryTable_variables_oid);
  623.     ROWAPI_init_table(&HistoryCtrlTable, "History", 0, &history_Create, NULL,   /* &history_Clone, */
  624.                       NULL,     /* &history_Delete, */
  625.                       &history_Validate,
  626.                       &history_Activate,
  627.                       &history_Deactivate, &history_Copy);
  628.     /*
  629.      * add_hist_entry (2, 3, 4, 2); 
  630.      */
  631. }