lcd_time.c
上传用户:cxs890
上传日期:2021-05-22
资源大小:347k
文件大小:12k
源码类别:

SNMP编程

开发平台:

C/C++

  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 <config.h>
  8. #include <sys/types.h>
  9. #if HAVE_WINSOCK_H
  10. #include <ip/socket.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 <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 "asn1.h"
  42. #include "snmp_api.h"
  43. #include "callback.h"
  44. #include "snmpusm.h"
  45. #include "lcd_time.h"
  46. #include "snmp_debug.h"
  47. #include "tools.h"
  48. #include "scapi.h"
  49. #include "transform_oids.h"
  50. /*
  51.  * Global static hashlist to contain Enginetime entries.
  52.  *
  53.  * New records are prepended to the appropriate list at the hash index.
  54.  */
  55. static Enginetime etimelist[ETIMELIST_SIZE];
  56. extern time_t time(time_t *);
  57. /*******************************************************************-o-******
  58.  * get_enginetime
  59.  *
  60.  * Parameters:
  61.  * *engineID
  62.  *  engineID_len
  63.  * *engineboot
  64.  * *engine_time
  65.  *      
  66.  * Returns:
  67.  * SNMPERR_SUCCESS Success -- when a record for engineID is found.
  68.  * SNMPERR_GENERR Otherwise.
  69.  *
  70.  *
  71.  * Lookup engineID and return the recorded values for the
  72.  * <engine_time, engineboot> tuple adjusted to reflect the estimated time
  73.  * at the engine in question.
  74.  *
  75.  * Special case: if engineID is NULL or if engineID_len is 0 then
  76.  * the time tuple is returned immediately as zero.
  77.  *
  78.  * XXX What if timediff wraps?  >shrug<
  79.  * XXX  Then: you need to increment the boots value.  Now.  Detecting
  80.  *            this is another matter.
  81.  */
  82. int
  83. get_enginetime( u_char *engineID,
  84. u_int  engineID_len,
  85. u_int *engineboot,
  86. u_int *engine_time,
  87. 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 = time(&timediff) - 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. /* FIX -- move this check up... should not change anything
  121.  * if engineboot is already locked.  ???
  122.  */
  123. if (*engineboot < ENGINEBOOT_MAX) {
  124. *engineboot += 1;
  125. }
  126. } else {
  127. *engine_time += timediff;
  128. }
  129.         DEBUGMSGTL(("lcd_get_enginetime", "engineID "));
  130.         DEBUGMSGHEX(("lcd_get_enginetime", engineID, engineID_len));
  131.         DEBUGMSG(("lcd_get_enginetime", ": boots=%d, time=%dn", *engineboot,
  132.                   *engine_time));
  133. get_enginetime_quit:
  134. return rval;
  135. }  /* end get_enginetime() */
  136. /*******************************************************************-o-******
  137.  * get_enginetime
  138.  *
  139.  * Parameters:
  140.  * *engineID
  141.  *  engineID_len
  142.  * *engineboot
  143.  * *engine_time
  144.  *      
  145.  * Returns:
  146.  * SNMPERR_SUCCESS Success -- when a record for engineID is found.
  147.  * SNMPERR_GENERR Otherwise.
  148.  *
  149.  *
  150.  * Lookup engineID and return the recorded values for the
  151.  * <engine_time, engineboot> tuple adjusted to reflect the estimated time
  152.  * at the engine in question.
  153.  *
  154.  * Special case: if engineID is NULL or if engineID_len is 0 then
  155.  * the time tuple is returned immediately as zero.
  156.  *
  157.  * XXX What if timediff wraps?  >shrug<
  158.  * XXX  Then: you need to increment the boots value.  Now.  Detecting
  159.  *            this is another matter.
  160.  */
  161. int
  162. get_enginetime_ex( u_char *engineID,
  163. u_int  engineID_len,
  164. u_int *engineboot,
  165. u_int *engine_time,
  166. u_int *last_engine_time,
  167. 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 = time(&timediff) - 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. /* FIX -- move this check up... should not change anything
  201.  * if engineboot is already locked.  ???
  202.  */
  203. if (*engineboot < ENGINEBOOT_MAX) {
  204. *engineboot += 1;
  205. }
  206. } else {
  207. *engine_time += timediff;
  208. }
  209.         DEBUGMSGTL(("lcd_get_enginetime_ex", "engineID "));
  210.         DEBUGMSGHEX(("lcd_get_enginetime_ex", engineID, engineID_len));
  211.         DEBUGMSG(("lcd_get_enginetime_ex", ": boots=%d, time=%dn", *engineboot,
  212.                   *engine_time));
  213. get_enginetime_ex_quit:
  214. return rval;
  215. }  /* end get_enginetime_ex() */
  216. /*******************************************************************-o-******
  217.  * set_enginetime
  218.  *
  219.  * Parameters:
  220.  * *engineID
  221.  *  engineID_len
  222.  *  engineboot
  223.  *  engine_time
  224.  *      
  225.  * Returns:
  226.  * SNMPERR_SUCCESS Success.
  227.  * SNMPERR_GENERR Otherwise.
  228.  *
  229.  *
  230.  * Lookup engineID and store the given <engine_time, engineboot> tuple
  231.  * and then stamp the record with a consistent source of local time.
  232.  * If the engineID record does not exist, create one.
  233.  *
  234.  * Special case: engineID is NULL or engineID_len is 0 defines an engineID
  235.  * that is "always set."
  236.  *
  237.  * XXX "Current time within the local engine" == time(NULL)...
  238.  */
  239. int
  240. set_enginetime( u_char *engineID,
  241. u_int  engineID_len,
  242. u_int  engineboot,
  243. u_int    engine_time,
  244. u_int    authenticated)
  245. {
  246. int rval = SNMPERR_SUCCESS,
  247. iindex;
  248. Enginetime e = NULL;
  249. time_t t_temp;
  250. /*
  251.  * Sanity check.
  252.  */
  253. if ( !engineID || (engineID_len <= 0) ) {
  254. return rval;
  255. }
  256. /*
  257.  * Store the given <engine_time, engineboot> tuple in the record
  258.  * for engineID.  Create a new record if necessary.
  259.  */
  260. if ( !(e = search_enginetime_list(engineID, engineID_len)) )
  261. {
  262. if ( (iindex = hash_engineID(engineID, engineID_len)) < 0 )
  263. {
  264. QUITFUN(SNMPERR_GENERR, set_enginetime_quit);
  265. }
  266. e = (Enginetime) calloc(1,sizeof(*e));
  267. e->next = etimelist[iindex];
  268. etimelist[iindex] = e;
  269. e->engineID = (u_char *) calloc(1,engineID_len);
  270. memcpy(e->engineID, engineID, engineID_len);
  271. e->engineID_len = engineID_len;
  272. }
  273. #ifdef LCD_TIME_SYNC_OPT
  274. if (authenticated || !e->authenticatedFlag) {
  275.   e->authenticatedFlag = authenticated;
  276. #else
  277. if (authenticated) {
  278. #endif
  279.   e->engineTime   = engine_time;
  280.   e->engineBoot   = engineboot;
  281.   e->lastReceivedEngineTime = time(&t_temp);
  282.         }
  283. e = NULL; /* Indicates a successful update. */
  284.         DEBUGMSGTL(("lcd_set_enginetime", "engineID "));
  285.         DEBUGMSGHEX(("lcd_set_enginetime", engineID, engineID_len));
  286.         DEBUGMSG(("lcd_set_enginetime", ": boots=%d, time=%dn", engineboot,
  287.                   engine_time));
  288. set_enginetime_quit:
  289. SNMP_FREE(e);
  290. return rval;
  291. }  /* end set_enginetime() */
  292. /*******************************************************************-o-******
  293.  * search_enginetime_list
  294.  *
  295.  * Parameters:
  296.  * *engineID
  297.  *  engineID_len
  298.  *      
  299.  * Returns:
  300.  * Pointer to a etimelist record with engineID <engineID>  -OR-
  301.  * NULL if no record exists.
  302.  *
  303.  *
  304.  * Search etimelist for an entry with engineID.
  305.  *
  306.  * ASSUMES that no engineID will have more than one record in the list.
  307.  */
  308. Enginetime
  309. search_enginetime_list(u_char *engineID, u_int engineID_len)
  310. {
  311. int rval = SNMPERR_SUCCESS;
  312. Enginetime e    = NULL;
  313. /*
  314.  * Sanity check.
  315.  */
  316. if ( !engineID || (engineID_len<=0) ) {
  317. QUITFUN(SNMPERR_GENERR, search_enginetime_list_quit);
  318. }
  319. /*
  320.  * Find the entry for engineID if there be one.
  321.  */
  322. rval = hash_engineID(engineID, engineID_len);
  323. if (rval < 0) {
  324. QUITFUN(SNMPERR_GENERR, search_enginetime_list_quit);
  325. }
  326. e = etimelist[rval];
  327. for ( /*EMPTY*/; e; e = e->next )
  328. {
  329. if ( (engineID_len == e->engineID_len)
  330. && !memcmp(e->engineID, engineID, engineID_len) )
  331. {
  332. break;
  333. }
  334. }
  335. search_enginetime_list_quit:
  336. return e;
  337. }  /* end search_enginetime_list() */
  338. /*******************************************************************-o-******
  339.  * hash_engineID
  340.  *
  341.  * Parameters:
  342.  * *engineID
  343.  *  engineID_len
  344.  *      
  345.  * Returns:
  346.  * >0 etimelist index for this engineID.
  347.  * SNMPERR_GENERR Error.
  348.  *
  349.  * 
  350.  * Use a cheap hash to build an index into the etimelist.  Method is 
  351.  * to hash the engineID, then split the hash into u_int's and add them up
  352.  * and modulo the size of the list.
  353.  *
  354.  */
  355. int
  356. hash_engineID(u_char *engineID, u_int engineID_len)
  357. {
  358. int  rval = SNMPERR_GENERR;
  359. size_t  buf_len = SNMP_MAXBUF;
  360. u_int  additive = 0;
  361. u_char *bufp,
  362.  buf[SNMP_MAXBUF];
  363. void *context = NULL;
  364. /*
  365.  * Sanity check.
  366.  */
  367. if ( !engineID || (engineID_len <= 0) ) {
  368. QUITFUN(SNMPERR_GENERR, hash_engineID_quit);
  369. }
  370. /*
  371.  * Hash engineID into a list index.
  372.  */
  373.         rval = sc_hash(usmHMACMD5AuthProtocol,
  374.                        sizeof(usmHMACMD5AuthProtocol)/sizeof(oid),
  375.                        engineID, engineID_len,
  376.                        buf, &buf_len);
  377. QUITFUN(rval, hash_engineID_quit);
  378.         
  379. for ( bufp = buf; (bufp-buf) < (int)buf_len; bufp += 4 ) {
  380. additive += (u_int) *bufp;
  381. }
  382. hash_engineID_quit:
  383. SNMP_FREE(context);
  384. memset(buf, 0, SNMP_MAXBUF);
  385. return (rval < 0) ? rval : (additive % ETIMELIST_SIZE);
  386. }  /* end hash_engineID() */
  387. #ifdef SNMP_TESTING_CODE
  388. /*******************************************************************-o-******
  389.  * dump_etimelist_entry
  390.  *
  391.  * Parameters:
  392.  * e
  393.  * count
  394.  */
  395. void
  396. dump_etimelist_entry(Enginetime e, int count)
  397. {
  398. u_int  buflen;
  399. char  tabs[SNMP_MAXBUF],
  400. *t = tabs, 
  401. *s;
  402. time_t  t_temp;
  403. count += 1;
  404. while (count--) {
  405. t += sprintf(t, "  ");
  406. }
  407. buflen = e->engineID_len;
  408. #ifdef SNMP_TESTING_CODE
  409. if ( !(s = dump_snmpEngineID(e->engineID, &buflen)) ) {
  410. #endif
  411. binary_to_hex(e->engineID, e->engineID_len, &s);
  412. #ifdef SNMP_TESTING_CODE
  413. }
  414. #endif
  415. DEBUGMSGTL(("dump_etimelist", "%sn",tabs));
  416. DEBUGMSGTL(("dump_etimelist", "%s%s (len=%d) <%d,%d>n", tabs,
  417.                     s, e->engineID_len,
  418.                     e->engineTime, e->engineBoot));
  419. DEBUGMSGTL(("dump_etimelist", "%s%ld (%ld) -- %s", tabs,
  420.                     e->lastReceivedEngineTime,
  421.                     time(&t_temp) - e->lastReceivedEngineTime,
  422.                     ctime(&e->lastReceivedEngineTime)));
  423. SNMP_FREE(s);
  424. }  /* end dump_etimelist_entry() */
  425. /*******************************************************************-o-******
  426.  * dump_etimelist
  427.  */
  428. void
  429. dump_etimelist(void)
  430. {
  431. int iindex = -1,
  432. count = 0;
  433. Enginetime e;
  434. DEBUGMSGTL(("dump_etimelist", "n"));
  435. while (++iindex < ETIMELIST_SIZE) {
  436. DEBUGMSG(("dump_etimelist", "[%d]", iindex));
  437. count = 0;
  438. e = etimelist[iindex];
  439. while (e) {
  440. dump_etimelist_entry(e, count++);
  441. e = e->next;
  442. }
  443. if (count > 0) {
  444. DEBUGMSG(("dump_etimelist", "n"));
  445. }
  446. }  /* endwhile */
  447. DEBUGMSG(("dump_etimelist", "n"));
  448. }  /* end dump_etimelist() */
  449. #endif /* SNMP_TESTING_CODE */