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

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  * lcd_time.c
  3.  *
  4.  * XXX  Should etimelist entries with <0,0> time tuples be timed out?
  5.  * XXX  Need a routine to free the memory?  (Perhaps at shutdown?)
  6.  */
  7. #include <net-snmp/net-snmp-config.h>
  8. #include <sys/types.h>
  9. #if HAVE_WINSOCK_H
  10. #include <winsock.h>
  11. #endif
  12. #include <stdio.h>
  13. #ifdef HAVE_STDLIB_H
  14. #include <stdlib.h>
  15. #endif
  16. #if HAVE_STRING_H
  17. #include <string.h>
  18. #else
  19. #include <strings.h>
  20. #endif
  21. #if TIME_WITH_SYS_TIME
  22. # ifdef WIN32
  23. #  include <sys/timeb.h>
  24. # else
  25. #  include <sys/time.h>
  26. # endif
  27. # include <time.h>
  28. #else
  29. # if HAVE_SYS_TIME_H
  30. #  include <sys/time.h>
  31. # else
  32. #  include <time.h>
  33. # endif
  34. #endif
  35. #ifdef HAVE_NETINET_IN_H
  36. #include <netinet/in.h>
  37. #endif
  38. #if HAVE_DMALLOC_H
  39. #include <dmalloc.h>
  40. #endif
  41. #include <net-snmp/types.h>
  42. #include <net-snmp/output_api.h>
  43. #include <net-snmp/utilities.h>
  44. #include <net-snmp/library/snmp_api.h>
  45. #include <net-snmp/library/callback.h>
  46. #include <net-snmp/library/snmp_secmod.h>
  47. #include <net-snmp/library/snmpusm.h>
  48. #include <net-snmp/library/lcd_time.h>
  49. #include <net-snmp/library/scapi.h>
  50. #include <net-snmp/library/snmpv3.h>
  51. #include <net-snmp/library/transform_oids.h>
  52. /*
  53.  * Global static hashlist to contain Enginetime entries.
  54.  *
  55.  * New records are prepended to the appropriate list at the hash index.
  56.  */
  57. static Enginetime etimelist[ETIMELIST_SIZE];
  58. /*******************************************************************-o-******
  59.  * get_enginetime
  60.  *
  61.  * Parameters:
  62.  * *engineID
  63.  *  engineID_len
  64.  * *engineboot
  65.  * *engine_time
  66.  *      
  67.  * Returns:
  68.  * SNMPERR_SUCCESS Success -- when a record for engineID is found.
  69.  * SNMPERR_GENERR Otherwise.
  70.  *
  71.  *
  72.  * Lookup engineID and return the recorded values for the
  73.  * <engine_time, engineboot> tuple adjusted to reflect the estimated time
  74.  * at the engine in question.
  75.  *
  76.  * Special case: if engineID is NULL or if engineID_len is 0 then
  77.  * the time tuple is returned immediately as zero.
  78.  *
  79.  * XXX What if timediff wraps?  >shrug<
  80.  * XXX  Then: you need to increment the boots value.  Now.  Detecting
  81.  *            this is another matter.
  82.  */
  83. int
  84. get_enginetime(u_char * engineID,
  85.                u_int engineID_len,
  86.                u_int * engineboot,
  87.                u_int * engine_time, u_int authenticated)
  88. {
  89.     int             rval = SNMPERR_SUCCESS;
  90.     time_t          timediff = 0;
  91.     Enginetime      e = NULL;
  92.     /*
  93.      * Sanity check.
  94.      */
  95.     if (!engine_time || !engineboot) {
  96.         QUITFUN(SNMPERR_GENERR, get_enginetime_quit);
  97.     }
  98.     /*
  99.      * Compute estimated current engine_time tuple at engineID if
  100.      * a record is cached for it.
  101.      */
  102.     *engine_time = *engineboot = 0;
  103.     if (!engineID || (engineID_len <= 0)) {
  104.         QUITFUN(SNMPERR_GENERR, get_enginetime_quit);
  105.     }
  106.     if (!(e = search_enginetime_list(engineID, engineID_len))) {
  107.         QUITFUN(SNMPERR_GENERR, get_enginetime_quit);
  108.     }
  109. #ifdef LCD_TIME_SYNC_OPT
  110.     if (!authenticated || e->authenticatedFlag) {
  111. #endif
  112.         *engine_time = e->engineTime;
  113.         *engineboot = e->engineBoot;
  114.        timediff = snmpv3_local_snmpEngineTime() - e->lastReceivedEngineTime;
  115. #ifdef LCD_TIME_SYNC_OPT
  116.     }
  117. #endif
  118.     if (timediff > (int) (ENGINETIME_MAX - *engine_time)) {
  119.         *engine_time = (timediff - (ENGINETIME_MAX - *engine_time));
  120.         /*
  121.          * FIX -- move this check up... should not change anything
  122.          * * if engineboot is already locked.  ???
  123.          */
  124.         if (*engineboot < ENGINEBOOT_MAX) {
  125.             *engineboot += 1;
  126.         }
  127.     } else {
  128.         *engine_time += timediff;
  129.     }
  130.     DEBUGMSGTL(("lcd_get_enginetime", "engineID "));
  131.     DEBUGMSGHEX(("lcd_get_enginetime", engineID, engineID_len));
  132.     DEBUGMSG(("lcd_get_enginetime", ": boots=%d, time=%dn", *engineboot,
  133.               *engine_time));
  134.   get_enginetime_quit:
  135.     return rval;
  136. }                               /* end get_enginetime() */
  137. /*******************************************************************-o-******
  138.  * get_enginetime
  139.  *
  140.  * Parameters:
  141.  * *engineID
  142.  *  engineID_len
  143.  * *engineboot
  144.  * *engine_time
  145.  *      
  146.  * Returns:
  147.  * SNMPERR_SUCCESS Success -- when a record for engineID is found.
  148.  * SNMPERR_GENERR Otherwise.
  149.  *
  150.  *
  151.  * Lookup engineID and return the recorded values for the
  152.  * <engine_time, engineboot> tuple adjusted to reflect the estimated time
  153.  * at the engine in question.
  154.  *
  155.  * Special case: if engineID is NULL or if engineID_len is 0 then
  156.  * the time tuple is returned immediately as zero.
  157.  *
  158.  * XXX What if timediff wraps?  >shrug<
  159.  * XXX  Then: you need to increment the boots value.  Now.  Detecting
  160.  *            this is another matter.
  161.  */
  162. int
  163. get_enginetime_ex(u_char * engineID,
  164.                   u_int engineID_len,
  165.                   u_int * engineboot,
  166.                   u_int * engine_time,
  167.                   u_int * last_engine_time, u_int authenticated)
  168. {
  169.     int             rval = SNMPERR_SUCCESS;
  170.     time_t          timediff = 0;
  171.     Enginetime      e = NULL;
  172.     /*
  173.      * Sanity check.
  174.      */
  175.     if (!engine_time || !engineboot || !last_engine_time) {
  176.         QUITFUN(SNMPERR_GENERR, get_enginetime_ex_quit);
  177.     }
  178.     /*
  179.      * Compute estimated current engine_time tuple at engineID if
  180.      * a record is cached for it.
  181.      */
  182.     *last_engine_time = *engine_time = *engineboot = 0;
  183.     if (!engineID || (engineID_len <= 0)) {
  184.         QUITFUN(SNMPERR_GENERR, get_enginetime_ex_quit);
  185.     }
  186.     if (!(e = search_enginetime_list(engineID, engineID_len))) {
  187.         QUITFUN(SNMPERR_GENERR, get_enginetime_ex_quit);
  188.     }
  189. #ifdef LCD_TIME_SYNC_OPT
  190.     if (!authenticated || e->authenticatedFlag) {
  191. #endif
  192.         *last_engine_time = *engine_time = e->engineTime;
  193.         *engineboot = e->engineBoot;
  194.        timediff = snmpv3_local_snmpEngineTime() - e->lastReceivedEngineTime;
  195. #ifdef LCD_TIME_SYNC_OPT
  196.     }
  197. #endif
  198.     if (timediff > (int) (ENGINETIME_MAX - *engine_time)) {
  199.         *engine_time = (timediff - (ENGINETIME_MAX - *engine_time));
  200.         /*
  201.          * FIX -- move this check up... should not change anything
  202.          * * if engineboot is already locked.  ???
  203.          */
  204.         if (*engineboot < ENGINEBOOT_MAX) {
  205.             *engineboot += 1;
  206.         }
  207.     } else {
  208.         *engine_time += timediff;
  209.     }
  210.     DEBUGMSGTL(("lcd_get_enginetime_ex", "engineID "));
  211.     DEBUGMSGHEX(("lcd_get_enginetime_ex", engineID, engineID_len));
  212.     DEBUGMSG(("lcd_get_enginetime_ex", ": boots=%d, time=%dn",
  213.               *engineboot, *engine_time));
  214.   get_enginetime_ex_quit:
  215.     return rval;
  216. }                               /* end get_enginetime_ex() */
  217. void free_enginetime(unsigned char *engineID, size_t engineID_len)
  218. {
  219.     Enginetime      e = NULL;
  220.     int             rval = 0;
  221.     rval = hash_engineID(engineID, engineID_len);
  222.     if (rval < 0)
  223. return;
  224.     e = etimelist[rval];
  225.     while (e != NULL) {
  226. etimelist[rval] = e->next;
  227. SNMP_FREE(e->engineID);
  228. SNMP_FREE(e);
  229. e = etimelist[rval];
  230.     }
  231. }
  232. /*******************************************************************-o-******
  233.  * set_enginetime
  234.  *
  235.  * Parameters:
  236.  * *engineID
  237.  *  engineID_len
  238.  *  engineboot
  239.  *  engine_time
  240.  *      
  241.  * Returns:
  242.  * SNMPERR_SUCCESS Success.
  243.  * SNMPERR_GENERR Otherwise.
  244.  *
  245.  *
  246.  * Lookup engineID and store the given <engine_time, engineboot> tuple
  247.  * and then stamp the record with a consistent source of local time.
  248.  * If the engineID record does not exist, create one.
  249.  *
  250.  * Special case: engineID is NULL or engineID_len is 0 defines an engineID
  251.  * that is "always set."
  252.  *
  253.  * XXX "Current time within the local engine" == time(NULL)...
  254.  */
  255. int
  256. set_enginetime(u_char * engineID,
  257.                u_int engineID_len,
  258.                u_int engineboot, u_int engine_time, u_int authenticated)
  259. {
  260.     int             rval = SNMPERR_SUCCESS, iindex;
  261.     Enginetime      e = NULL;
  262.     /*
  263.      * Sanity check.
  264.      */
  265.     if (!engineID || (engineID_len <= 0)) {
  266.         return rval;
  267.     }
  268.     /*
  269.      * Store the given <engine_time, engineboot> tuple in the record
  270.      * for engineID.  Create a new record if necessary.
  271.      */
  272.     if (!(e = search_enginetime_list(engineID, engineID_len))) {
  273.         if ((iindex = hash_engineID(engineID, engineID_len)) < 0) {
  274.             QUITFUN(SNMPERR_GENERR, set_enginetime_quit);
  275.         }
  276.         e = (Enginetime) calloc(1, sizeof(*e));
  277.         e->next = etimelist[iindex];
  278.         etimelist[iindex] = e;
  279.         e->engineID = (u_char *) calloc(1, engineID_len);
  280.         memcpy(e->engineID, engineID, engineID_len);
  281.         e->engineID_len = engineID_len;
  282.     }
  283. #ifdef LCD_TIME_SYNC_OPT
  284.     if (authenticated || !e->authenticatedFlag) {
  285.         e->authenticatedFlag = authenticated;
  286. #else
  287.     if (authenticated) {
  288. #endif
  289.         e->engineTime = engine_time;
  290.         e->engineBoot = engineboot;
  291.         e->lastReceivedEngineTime = snmpv3_local_snmpEngineTime();
  292.     }
  293.     e = NULL;                   /* Indicates a successful update. */
  294.     DEBUGMSGTL(("lcd_set_enginetime", "engineID "));
  295.     DEBUGMSGHEX(("lcd_set_enginetime", engineID, engineID_len));
  296.     DEBUGMSG(("lcd_set_enginetime", ": boots=%d, time=%dn", engineboot,
  297.               engine_time));
  298.   set_enginetime_quit:
  299.     SNMP_FREE(e);
  300.     return rval;
  301. }                               /* end set_enginetime() */
  302. /*******************************************************************-o-******
  303.  * search_enginetime_list
  304.  *
  305.  * Parameters:
  306.  * *engineID
  307.  *  engineID_len
  308.  *      
  309.  * Returns:
  310.  * Pointer to a etimelist record with engineID <engineID>  -OR-
  311.  * NULL if no record exists.
  312.  *
  313.  *
  314.  * Search etimelist for an entry with engineID.
  315.  *
  316.  * ASSUMES that no engineID will have more than one record in the list.
  317.  */
  318. Enginetime
  319. search_enginetime_list(u_char * engineID, u_int engineID_len)
  320. {
  321.     int             rval = SNMPERR_SUCCESS;
  322.     Enginetime      e = NULL;
  323.     /*
  324.      * Sanity check.
  325.      */
  326.     if (!engineID || (engineID_len <= 0)) {
  327.         QUITFUN(SNMPERR_GENERR, search_enginetime_list_quit);
  328.     }
  329.     /*
  330.      * Find the entry for engineID if there be one.
  331.      */
  332.     rval = hash_engineID(engineID, engineID_len);
  333.     if (rval < 0) {
  334.         QUITFUN(SNMPERR_GENERR, search_enginetime_list_quit);
  335.     }
  336.     e = etimelist[rval];
  337.     for ( /*EMPTY*/; e; e = e->next) {
  338.         if ((engineID_len == e->engineID_len)
  339.             && !memcmp(e->engineID, engineID, engineID_len)) {
  340.             break;
  341.         }
  342.     }
  343.   search_enginetime_list_quit:
  344.     return e;
  345. }                               /* end search_enginetime_list() */
  346. /*******************************************************************-o-******
  347.  * hash_engineID
  348.  *
  349.  * Parameters:
  350.  * *engineID
  351.  *  engineID_len
  352.  *      
  353.  * Returns:
  354.  * >0 etimelist index for this engineID.
  355.  * SNMPERR_GENERR Error.
  356.  *
  357.  * 
  358.  * Use a cheap hash to build an index into the etimelist.  Method is 
  359.  * to hash the engineID, then split the hash into u_int's and add them up
  360.  * and modulo the size of the list.
  361.  *
  362.  */
  363. int
  364. hash_engineID(u_char * engineID, u_int engineID_len)
  365. {
  366.     int             rval = SNMPERR_GENERR;
  367.     size_t          buf_len = SNMP_MAXBUF;
  368.     u_int           additive = 0;
  369.     u_char         *bufp, buf[SNMP_MAXBUF];
  370.     void           *context = NULL;
  371.     /*
  372.      * Sanity check.
  373.      */
  374.     if (!engineID || (engineID_len <= 0)) {
  375.         QUITFUN(SNMPERR_GENERR, hash_engineID_quit);
  376.     }
  377.     /*
  378.      * Hash engineID into a list index.
  379.      */
  380. #ifndef DISABLE_MD5
  381.     rval = sc_hash(usmHMACMD5AuthProtocol,
  382.                    sizeof(usmHMACMD5AuthProtocol) / sizeof(oid),
  383.                    engineID, engineID_len, buf, &buf_len);
  384. #else
  385.     rval = sc_hash(usmHMACSHA1AuthProtocol,
  386.                    sizeof(usmHMACSHA1AuthProtocol) / sizeof(oid),
  387.                    engineID, engineID_len, buf, &buf_len);
  388. #endif
  389.     QUITFUN(rval, hash_engineID_quit);
  390.     for (bufp = buf; (bufp - buf) < (int) buf_len; bufp += 4) {
  391.         additive += (u_int) * bufp;
  392.     }
  393.   hash_engineID_quit:
  394.     SNMP_FREE(context);
  395.     memset(buf, 0, SNMP_MAXBUF);
  396.     return (rval < 0) ? rval : (additive % ETIMELIST_SIZE);
  397. }                               /* end hash_engineID() */
  398. #ifdef SNMP_TESTING_CODE
  399. /*******************************************************************-o-******
  400.  * dump_etimelist_entry
  401.  *
  402.  * Parameters:
  403.  * e
  404.  * count
  405.  */
  406. void
  407. dump_etimelist_entry(Enginetime e, int count)
  408. {
  409.     u_int           buflen;
  410.     char            tabs[SNMP_MAXBUF], *t = tabs, *s;
  411.     count += 1;
  412.     while (count--) {
  413.         t += sprintf(t, "  ");
  414.     }
  415.     buflen = e->engineID_len;
  416. #ifdef SNMP_TESTING_CODE
  417.     if (!(s = dump_snmpEngineID(e->engineID, &buflen))) {
  418. #endif
  419.         binary_to_hex(e->engineID, e->engineID_len, &s);
  420. #ifdef SNMP_TESTING_CODE
  421.     }
  422. #endif
  423.     DEBUGMSGTL(("dump_etimelist", "%sn", tabs));
  424.     DEBUGMSGTL(("dump_etimelist", "%s%s (len=%d) <%d,%d>n", tabs,
  425.                 s, e->engineID_len, e->engineTime, e->engineBoot));
  426.     DEBUGMSGTL(("dump_etimelist", "%s%ld (%ld)", tabs,
  427.                 e->lastReceivedEngineTime,
  428.                 snmpv3_local_snmpEngineTime() - e->lastReceivedEngineTime));
  429.     SNMP_FREE(s);
  430. }                               /* end dump_etimelist_entry() */
  431. /*******************************************************************-o-******
  432.  * dump_etimelist
  433.  */
  434. void
  435. dump_etimelist(void)
  436. {
  437.     int             iindex = -1, count = 0;
  438.     Enginetime      e;
  439.     DEBUGMSGTL(("dump_etimelist", "n"));
  440.     while (++iindex < ETIMELIST_SIZE) {
  441.         DEBUGMSG(("dump_etimelist", "[%d]", iindex));
  442.         count = 0;
  443.         e = etimelist[iindex];
  444.         while (e) {
  445.             dump_etimelist_entry(e, count++);
  446.             e = e->next;
  447.         }
  448.         if (count > 0) {
  449.             DEBUGMSG(("dump_etimelist", "n"));
  450.         }
  451.     }                           /* endwhile */
  452.     DEBUGMSG(("dump_etimelist", "n"));
  453. }                               /* end dump_etimelist() */
  454. #endif                          /* SNMP_TESTING_CODE */