lcd_time.c

00001 /*
00002  * lcd_time.c
00003  *
00004  * XXX  Should etimelist entries with <0,0> time tuples be timed out?
00005  * XXX  Need a routine to free the memory?  (Perhaps at shutdown?)
00006  */
00007 
00008 #include <net-snmp/net-snmp-config.h>
00009 
00010 #include <sys/types.h>
00011 #if HAVE_WINSOCK_H
00012 #include <winsock.h>
00013 #endif
00014 #include <stdio.h>
00015 #ifdef HAVE_STDLIB_H
00016 #include <stdlib.h>
00017 #endif
00018 #if HAVE_STRING_H
00019 #include <string.h>
00020 #else
00021 #include <strings.h>
00022 #endif
00023 #if TIME_WITH_SYS_TIME
00024 # ifdef WIN32
00025 #  include <sys/timeb.h>
00026 # else
00027 #  include <sys/time.h>
00028 # endif
00029 # include <time.h>
00030 #else
00031 # if HAVE_SYS_TIME_H
00032 #  include <sys/time.h>
00033 # else
00034 #  include <time.h>
00035 # endif
00036 #endif
00037 #ifdef HAVE_NETINET_IN_H
00038 #include <netinet/in.h>
00039 #endif
00040 
00041 #if HAVE_DMALLOC_H
00042 #include <dmalloc.h>
00043 #endif
00044 
00045 #include <net-snmp/types.h>
00046 #include <net-snmp/output_api.h>
00047 #include <net-snmp/utilities.h>
00048 
00049 #include <net-snmp/library/snmp_api.h>
00050 #include <net-snmp/library/callback.h>
00051 #include <net-snmp/library/snmp_secmod.h>
00052 #include <net-snmp/library/snmpusm.h>
00053 #include <net-snmp/library/lcd_time.h>
00054 #include <net-snmp/library/scapi.h>
00055 #include <net-snmp/library/snmpv3.h>
00056 
00057 #include <net-snmp/library/transform_oids.h>
00058 
00059 /*
00060  * Global static hashlist to contain Enginetime entries.
00061  *
00062  * New records are prepended to the appropriate list at the hash index.
00063  */
00064 static Enginetime etimelist[ETIMELIST_SIZE];
00065 
00066 
00067 
00068 
00069 /*******************************************************************-o-******
00070  * get_enginetime
00071  *
00072  * Parameters:
00073  *      *engineID
00074  *       engineID_len
00075  *      *engineboot
00076  *      *engine_time
00077  *      
00078  * Returns:
00079  *      SNMPERR_SUCCESS         Success -- when a record for engineID is found.
00080  *      SNMPERR_GENERR          Otherwise.
00081  *
00082  *
00083  * Lookup engineID and return the recorded values for the
00084  * <engine_time, engineboot> tuple adjusted to reflect the estimated time
00085  * at the engine in question.
00086  *
00087  * Special case: if engineID is NULL or if engineID_len is 0 then
00088  * the time tuple is returned immediately as zero.
00089  *
00090  * XXX  What if timediff wraps?  >shrug<
00091  * XXX  Then: you need to increment the boots value.  Now.  Detecting
00092  *            this is another matter.
00093  */
00094 int
00095 get_enginetime(u_char * engineID,
00096                u_int engineID_len,
00097                u_int * engineboot,
00098                u_int * engine_time, u_int authenticated)
00099 {
00100     int             rval = SNMPERR_SUCCESS;
00101     time_t          timediff = 0;
00102     Enginetime      e = NULL;
00103 
00104 
00105 
00106     /*
00107      * Sanity check.
00108      */
00109     if (!engine_time || !engineboot) {
00110         QUITFUN(SNMPERR_GENERR, get_enginetime_quit);
00111     }
00112 
00113 
00114     /*
00115      * Compute estimated current engine_time tuple at engineID if
00116      * a record is cached for it.
00117      */
00118     *engine_time = *engineboot = 0;
00119 
00120     if (!engineID || (engineID_len <= 0)) {
00121         QUITFUN(SNMPERR_GENERR, get_enginetime_quit);
00122     }
00123 
00124     if (!(e = search_enginetime_list(engineID, engineID_len))) {
00125         QUITFUN(SNMPERR_GENERR, get_enginetime_quit);
00126     }
00127 #ifdef LCD_TIME_SYNC_OPT
00128     if (!authenticated || e->authenticatedFlag) {
00129 #endif
00130         *engine_time = e->engineTime;
00131         *engineboot = e->engineBoot;
00132 
00133        timediff = snmpv3_local_snmpEngineTime() - e->lastReceivedEngineTime;
00134 
00135 #ifdef LCD_TIME_SYNC_OPT
00136     }
00137 #endif
00138 
00139     if (timediff > (int) (ENGINETIME_MAX - *engine_time)) {
00140         *engine_time = (timediff - (ENGINETIME_MAX - *engine_time));
00141 
00142         /*
00143          * FIX -- move this check up... should not change anything
00144          * * if engineboot is already locked.  ???
00145          */
00146         if (*engineboot < ENGINEBOOT_MAX) {
00147             *engineboot += 1;
00148         }
00149 
00150     } else {
00151         *engine_time += timediff;
00152     }
00153 
00154     DEBUGMSGTL(("lcd_get_enginetime", "engineID "));
00155     DEBUGMSGHEX(("lcd_get_enginetime", engineID, engineID_len));
00156     DEBUGMSG(("lcd_get_enginetime", ": boots=%d, time=%d\n", *engineboot,
00157               *engine_time));
00158 
00159   get_enginetime_quit:
00160     return rval;
00161 
00162 }                               /* end get_enginetime() */
00163 
00164 /*******************************************************************-o-******
00165  * get_enginetime
00166  *
00167  * Parameters:
00168  *      *engineID
00169  *       engineID_len
00170  *      *engineboot
00171  *      *engine_time
00172  *      
00173  * Returns:
00174  *      SNMPERR_SUCCESS         Success -- when a record for engineID is found.
00175  *      SNMPERR_GENERR          Otherwise.
00176  *
00177  *
00178  * Lookup engineID and return the recorded values for the
00179  * <engine_time, engineboot> tuple adjusted to reflect the estimated time
00180  * at the engine in question.
00181  *
00182  * Special case: if engineID is NULL or if engineID_len is 0 then
00183  * the time tuple is returned immediately as zero.
00184  *
00185  * XXX  What if timediff wraps?  >shrug<
00186  * XXX  Then: you need to increment the boots value.  Now.  Detecting
00187  *            this is another matter.
00188  */
00189 int
00190 get_enginetime_ex(u_char * engineID,
00191                   u_int engineID_len,
00192                   u_int * engineboot,
00193                   u_int * engine_time,
00194                   u_int * last_engine_time, u_int authenticated)
00195 {
00196     int             rval = SNMPERR_SUCCESS;
00197     time_t          timediff = 0;
00198     Enginetime      e = NULL;
00199 
00200 
00201 
00202     /*
00203      * Sanity check.
00204      */
00205     if (!engine_time || !engineboot || !last_engine_time) {
00206         QUITFUN(SNMPERR_GENERR, get_enginetime_ex_quit);
00207     }
00208 
00209 
00210     /*
00211      * Compute estimated current engine_time tuple at engineID if
00212      * a record is cached for it.
00213      */
00214     *last_engine_time = *engine_time = *engineboot = 0;
00215 
00216     if (!engineID || (engineID_len <= 0)) {
00217         QUITFUN(SNMPERR_GENERR, get_enginetime_ex_quit);
00218     }
00219 
00220     if (!(e = search_enginetime_list(engineID, engineID_len))) {
00221         QUITFUN(SNMPERR_GENERR, get_enginetime_ex_quit);
00222     }
00223 #ifdef LCD_TIME_SYNC_OPT
00224     if (!authenticated || e->authenticatedFlag) {
00225 #endif
00226         *last_engine_time = *engine_time = e->engineTime;
00227         *engineboot = e->engineBoot;
00228 
00229        timediff = snmpv3_local_snmpEngineTime() - e->lastReceivedEngineTime;
00230 
00231 #ifdef LCD_TIME_SYNC_OPT
00232     }
00233 #endif
00234 
00235     if (timediff > (int) (ENGINETIME_MAX - *engine_time)) {
00236         *engine_time = (timediff - (ENGINETIME_MAX - *engine_time));
00237 
00238         /*
00239          * FIX -- move this check up... should not change anything
00240          * * if engineboot is already locked.  ???
00241          */
00242         if (*engineboot < ENGINEBOOT_MAX) {
00243             *engineboot += 1;
00244         }
00245 
00246     } else {
00247         *engine_time += timediff;
00248     }
00249 
00250     DEBUGMSGTL(("lcd_get_enginetime_ex", "engineID "));
00251     DEBUGMSGHEX(("lcd_get_enginetime_ex", engineID, engineID_len));
00252     DEBUGMSG(("lcd_get_enginetime_ex", ": boots=%d, time=%d\n",
00253               *engineboot, *engine_time));
00254 
00255   get_enginetime_ex_quit:
00256     return rval;
00257 
00258 }                               /* end get_enginetime_ex() */
00259 
00260 
00261 void free_enginetime(unsigned char *engineID, size_t engineID_len)
00262 {
00263     Enginetime      e = NULL;
00264     int             rval = 0;
00265 
00266     rval = hash_engineID(engineID, engineID_len);
00267     if (rval < 0)
00268         return;
00269 
00270     e = etimelist[rval];
00271 
00272     while (e != NULL) {
00273         etimelist[rval] = e->next;
00274         SNMP_FREE(e->engineID);
00275         SNMP_FREE(e);
00276         e = etimelist[rval];
00277     }
00278 
00279 }
00280 
00281 
00282 
00283 /*******************************************************************-o-******
00284  * set_enginetime
00285  *
00286  * Parameters:
00287  *      *engineID
00288  *       engineID_len
00289  *       engineboot
00290  *       engine_time
00291  *      
00292  * Returns:
00293  *      SNMPERR_SUCCESS         Success.
00294  *      SNMPERR_GENERR          Otherwise.
00295  *
00296  *
00297  * Lookup engineID and store the given <engine_time, engineboot> tuple
00298  * and then stamp the record with a consistent source of local time.
00299  * If the engineID record does not exist, create one.
00300  *
00301  * Special case: engineID is NULL or engineID_len is 0 defines an engineID
00302  * that is "always set."
00303  *
00304  * XXX  "Current time within the local engine" == time(NULL)...
00305  */
00306 int
00307 set_enginetime(u_char * engineID,
00308                u_int engineID_len,
00309                u_int engineboot, u_int engine_time, u_int authenticated)
00310 {
00311     int             rval = SNMPERR_SUCCESS, iindex;
00312     Enginetime      e = NULL;
00313 
00314 
00315 
00316     /*
00317      * Sanity check.
00318      */
00319     if (!engineID || (engineID_len <= 0)) {
00320         return rval;
00321     }
00322 
00323 
00324     /*
00325      * Store the given <engine_time, engineboot> tuple in the record
00326      * for engineID.  Create a new record if necessary.
00327      */
00328     if (!(e = search_enginetime_list(engineID, engineID_len))) {
00329         if ((iindex = hash_engineID(engineID, engineID_len)) < 0) {
00330             QUITFUN(SNMPERR_GENERR, set_enginetime_quit);
00331         }
00332 
00333         e = (Enginetime) calloc(1, sizeof(*e));
00334 
00335         e->next = etimelist[iindex];
00336         etimelist[iindex] = e;
00337 
00338         e->engineID = (u_char *) calloc(1, engineID_len);
00339         memcpy(e->engineID, engineID, engineID_len);
00340 
00341         e->engineID_len = engineID_len;
00342     }
00343 #ifdef LCD_TIME_SYNC_OPT
00344     if (authenticated || !e->authenticatedFlag) {
00345         e->authenticatedFlag = authenticated;
00346 #else
00347     if (authenticated) {
00348 #endif
00349         e->engineTime = engine_time;
00350         e->engineBoot = engineboot;
00351         e->lastReceivedEngineTime = snmpv3_local_snmpEngineTime();
00352     }
00353 
00354     e = NULL;                   /* Indicates a successful update. */
00355 
00356     DEBUGMSGTL(("lcd_set_enginetime", "engineID "));
00357     DEBUGMSGHEX(("lcd_set_enginetime", engineID, engineID_len));
00358     DEBUGMSG(("lcd_set_enginetime", ": boots=%d, time=%d\n", engineboot,
00359               engine_time));
00360 
00361   set_enginetime_quit:
00362     SNMP_FREE(e);
00363 
00364     return rval;
00365 
00366 }                               /* end set_enginetime() */
00367 
00368 
00369 
00370 
00371 /*******************************************************************-o-******
00372  * search_enginetime_list
00373  *
00374  * Parameters:
00375  *      *engineID
00376  *       engineID_len
00377  *      
00378  * Returns:
00379  *      Pointer to a etimelist record with engineID <engineID>  -OR-
00380  *      NULL if no record exists.
00381  *
00382  *
00383  * Search etimelist for an entry with engineID.
00384  *
00385  * ASSUMES that no engineID will have more than one record in the list.
00386  */
00387 Enginetime
00388 search_enginetime_list(u_char * engineID, u_int engineID_len)
00389 {
00390     int             rval = SNMPERR_SUCCESS;
00391     Enginetime      e = NULL;
00392 
00393 
00394     /*
00395      * Sanity check.
00396      */
00397     if (!engineID || (engineID_len <= 0)) {
00398         QUITFUN(SNMPERR_GENERR, search_enginetime_list_quit);
00399     }
00400 
00401 
00402     /*
00403      * Find the entry for engineID if there be one.
00404      */
00405     rval = hash_engineID(engineID, engineID_len);
00406     if (rval < 0) {
00407         QUITFUN(SNMPERR_GENERR, search_enginetime_list_quit);
00408     }
00409     e = etimelist[rval];
00410 
00411     for ( /*EMPTY*/; e; e = e->next) {
00412         if ((engineID_len == e->engineID_len)
00413             && !memcmp(e->engineID, engineID, engineID_len)) {
00414             break;
00415         }
00416     }
00417 
00418 
00419   search_enginetime_list_quit:
00420     return e;
00421 
00422 }                               /* end search_enginetime_list() */
00423 
00424 
00425 
00426 
00427 
00428 /*******************************************************************-o-******
00429  * hash_engineID
00430  *
00431  * Parameters:
00432  *      *engineID
00433  *       engineID_len
00434  *      
00435  * Returns:
00436  *      >0                      etimelist index for this engineID.
00437  *      SNMPERR_GENERR          Error.
00438  *      
00439  * 
00440  * Use a cheap hash to build an index into the etimelist.  Method is 
00441  * to hash the engineID, then split the hash into u_int's and add them up
00442  * and modulo the size of the list.
00443  *
00444  */
00445 int
00446 hash_engineID(u_char * engineID, u_int engineID_len)
00447 {
00448     int             rval = SNMPERR_GENERR;
00449     size_t          buf_len = SNMP_MAXBUF;
00450     u_int           additive = 0;
00451     u_char         *bufp, buf[SNMP_MAXBUF];
00452     void           *context = NULL;
00453 
00454 
00455 
00456     /*
00457      * Sanity check.
00458      */
00459     if (!engineID || (engineID_len <= 0)) {
00460         QUITFUN(SNMPERR_GENERR, hash_engineID_quit);
00461     }
00462 
00463 
00464     /*
00465      * Hash engineID into a list index.
00466      */
00467 #ifndef DISABLE_MD5
00468     rval = sc_hash(usmHMACMD5AuthProtocol,
00469                    sizeof(usmHMACMD5AuthProtocol) / sizeof(oid),
00470                    engineID, engineID_len, buf, &buf_len);
00471 #else
00472     rval = sc_hash(usmHMACSHA1AuthProtocol,
00473                    sizeof(usmHMACSHA1AuthProtocol) / sizeof(oid),
00474                    engineID, engineID_len, buf, &buf_len);
00475 #endif
00476     QUITFUN(rval, hash_engineID_quit);
00477 
00478     for (bufp = buf; (bufp - buf) < (int) buf_len; bufp += 4) {
00479         additive += (u_int) * bufp;
00480     }
00481 
00482   hash_engineID_quit:
00483     SNMP_FREE(context);
00484     memset(buf, 0, SNMP_MAXBUF);
00485 
00486     return (rval < 0) ? rval : (additive % ETIMELIST_SIZE);
00487 
00488 }                               /* end hash_engineID() */
00489 
00490 
00491 
00492 
00493 #ifdef SNMP_TESTING_CODE
00494 /*******************************************************************-o-******
00495  * dump_etimelist_entry
00496  *
00497  * Parameters:
00498  *      e
00499  *      count
00500  */
00501 void
00502 dump_etimelist_entry(Enginetime e, int count)
00503 {
00504     u_int           buflen;
00505     char            tabs[SNMP_MAXBUF], *t = tabs, *s;
00506 
00507 
00508 
00509     count += 1;
00510     while (count--) {
00511         t += sprintf(t, "  ");
00512     }
00513 
00514 
00515     buflen = e->engineID_len;
00516 #ifdef SNMP_TESTING_CODE
00517     if (!(s = dump_snmpEngineID(e->engineID, &buflen))) {
00518 #endif
00519         binary_to_hex(e->engineID, e->engineID_len, &s);
00520 #ifdef SNMP_TESTING_CODE
00521     }
00522 #endif
00523 
00524     DEBUGMSGTL(("dump_etimelist", "%s\n", tabs));
00525     DEBUGMSGTL(("dump_etimelist", "%s%s (len=%d) <%d,%d>\n", tabs,
00526                 s, e->engineID_len, e->engineTime, e->engineBoot));
00527     DEBUGMSGTL(("dump_etimelist", "%s%ld (%ld)", tabs,
00528                 e->lastReceivedEngineTime,
00529                 snmpv3_local_snmpEngineTime() - e->lastReceivedEngineTime));
00530 
00531     SNMP_FREE(s);
00532 
00533 }                               /* end dump_etimelist_entry() */
00534 
00535 
00536 
00537 
00538 /*******************************************************************-o-******
00539  * dump_etimelist
00540  */
00541 void
00542 dump_etimelist(void)
00543 {
00544     int             iindex = -1, count = 0;
00545     Enginetime      e;
00546 
00547 
00548 
00549     DEBUGMSGTL(("dump_etimelist", "\n"));
00550 
00551     while (++iindex < ETIMELIST_SIZE) {
00552         DEBUGMSG(("dump_etimelist", "[%d]", iindex));
00553 
00554         count = 0;
00555         e = etimelist[iindex];
00556 
00557         while (e) {
00558             dump_etimelist_entry(e, count++);
00559             e = e->next;
00560         }
00561 
00562         if (count > 0) {
00563             DEBUGMSG(("dump_etimelist", "\n"));
00564         }
00565     }                           /* endwhile */
00566 
00567     DEBUGMSG(("dump_etimelist", "\n"));
00568 
00569 }                               /* end dump_etimelist() */
00570 #endif                          /* SNMP_TESTING_CODE */

net-snmpに対してSat Sep 5 13:14:21 2009に生成されました。  doxygen 1.4.7