comparison packages/net/snmp/lib/current/src/lcd_time.c @ 103:95f3e12a6327 ecos-sw-2000-06-23

Merge from eCos master repository on 2000-06-23-16:41:10-BST
author jlarmour
date Fri, 23 Jun 2000 17:06:31 +0000
parents
children e0c0827131d1
comparison
equal deleted inserted replaced
102:6409b6d94dd7 103:95f3e12a6327
1 //==========================================================================
2 //
3 // ./lib/current/src/lcd_time.c
4 //
5 //
6 //==========================================================================
7 //####COPYRIGHTBEGIN####
8 //
9 // -------------------------------------------
10 // The contents of this file are subject to the Red Hat eCos Public License
11 // Version 1.1 (the "License"); you may not use this file except in
12 // compliance with the License. You may obtain a copy of the License at
13 // http://www.redhat.com/
14 //
15 // Software distributed under the License is distributed on an "AS IS"
16 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
17 // License for the specific language governing rights and limitations under
18 // the License.
19 //
20 // The Original Code is eCos - Embedded Configurable Operating System,
21 // released September 30, 1998.
22 //
23 // The Initial Developer of the Original Code is Red Hat.
24 // Portions created by Red Hat are
25 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
26 // All Rights Reserved.
27 // -------------------------------------------
28 //
29 //####COPYRIGHTEND####
30 //####UCDSNMPCOPYRIGHTBEGIN####
31 //
32 // -------------------------------------------
33 //
34 // Portions of this software may have been derived from the UCD-SNMP
35 // project, <http://ucd-snmp.ucdavis.edu/> from the University of
36 // California at Davis, which was originally based on the Carnegie Mellon
37 // University SNMP implementation. Portions of this software are therefore
38 // covered by the appropriate copyright disclaimers included herein.
39 //
40 // The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2"
41 // -------------------------------------------
42 //
43 //####UCDSNMPCOPYRIGHTEND####
44 //==========================================================================
45 //#####DESCRIPTIONBEGIN####
46 //
47 // Author(s): hmt
48 // Contributors: hmt
49 // Date: 2000-05-30
50 // Purpose: Port of UCD-SNMP distribution to eCos.
51 // Description:
52 //
53 //
54 //####DESCRIPTIONEND####
55 //
56 //==========================================================================
57 /********************************************************************
58 Copyright 1989, 1991, 1992 by Carnegie Mellon University
59
60 Derivative Work -
61 Copyright 1996, 1998, 1999, 2000 The Regents of the University of California
62
63 All Rights Reserved
64
65 Permission to use, copy, modify and distribute this software and its
66 documentation for any purpose and without fee is hereby granted,
67 provided that the above copyright notice appears in all copies and
68 that both that copyright notice and this permission notice appear in
69 supporting documentation, and that the name of CMU and The Regents of
70 the University of California not be used in advertising or publicity
71 pertaining to distribution of the software without specific written
72 permission.
73
74 CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL
75 WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
76 WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR
77 THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL,
78 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
79 FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
80 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
81 CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
82 *********************************************************************/
83 /*
84 * lcd_time.c
85 *
86 * XXX Should etimelist entries with <0,0> time tuples be timed out?
87 * XXX Need a routine to free the memory? (Perhaps at shutdown?)
88 */
89
90 #include <config.h>
91
92 #include <sys/types.h>
93 #if HAVE_WINSOCK_H
94 #include <winsock.h>
95 #endif
96 #include <stdio.h>
97 #ifdef HAVE_STDLIB_H
98 #include <stdlib.h>
99 #endif
100 #if HAVE_STRING_H
101 #include <string.h>
102 #else
103 #include <strings.h>
104 #endif
105 #if TIME_WITH_SYS_TIME
106 # ifdef WIN32
107 # include <sys/timeb.h>
108 # else
109 # include <sys/time.h>
110 # endif
111 # include <time.h>
112 #else
113 # if HAVE_SYS_TIME_H
114 # include <sys/time.h>
115 # else
116 # include <time.h>
117 # endif
118 #endif
119 #ifdef HAVE_NETINET_IN_H
120 #include <netinet/in.h>
121 #endif
122
123 #if HAVE_DMALLOC_H
124 #include <dmalloc.h>
125 #endif
126
127 #include "asn1.h"
128 #include "snmp_api.h"
129 #include "callback.h"
130 #include "snmpusm.h"
131 #include "lcd_time.h"
132 #include "snmp_debug.h"
133 #include "tools.h"
134 #include "scapi.h"
135
136 #include "transform_oids.h"
137
138
139 /*
140 * Global static hashlist to contain Enginetime entries.
141 *
142 * New records are prepended to the appropriate list at the hash index.
143 */
144 static Enginetime etimelist[ETIMELIST_SIZE];
145
146
147
148
149 /*******************************************************************-o-******
150 * get_enginetime
151 *
152 * Parameters:
153 * *engineID
154 * engineID_len
155 * *engineboot
156 * *engine_time
157 *
158 * Returns:
159 * SNMPERR_SUCCESS Success -- when a record for engineID is found.
160 * SNMPERR_GENERR Otherwise.
161 *
162 *
163 * Lookup engineID and return the recorded values for the
164 * <engine_time, engineboot> tuple adjusted to reflect the estimated time
165 * at the engine in question.
166 *
167 * Special case: if engineID is NULL or if engineID_len is 0 then
168 * the time tuple is returned immediately as zero.
169 *
170 * XXX What if timediff wraps? >shrug<
171 * XXX Then: you need to increment the boots value. Now. Detecting
172 * this is another matter.
173 */
174 int
175 get_enginetime( u_char *engineID,
176 u_int engineID_len,
177 u_int *engineboot,
178 u_int *engine_time,
179 u_int authenticated)
180 {
181 int rval = SNMPERR_SUCCESS;
182 time_t timediff = 0;
183 Enginetime e = NULL;
184
185
186
187 /*
188 * Sanity check.
189 */
190 if ( !engine_time || !engineboot ) {
191 QUITFUN(SNMPERR_GENERR, get_enginetime_quit);
192 }
193
194
195 /*
196 * Compute estimated current engine_time tuple at engineID if
197 * a record is cached for it.
198 */
199 *engine_time = *engineboot = 0;
200
201 if ( !engineID || (engineID_len<=0) ) {
202 QUITFUN(SNMPERR_GENERR, get_enginetime_quit);
203 }
204
205 if ( !(e = search_enginetime_list(engineID, engineID_len)) ) {
206 QUITFUN(SNMPERR_GENERR, get_enginetime_quit);
207 }
208
209 #ifdef LCD_TIME_SYNC_OPT
210 if (!authenticated || e->authenticatedFlag) {
211 #endif
212 *engine_time = e->engineTime;
213 *engineboot = e->engineBoot;
214
215 timediff = time(NULL) - e->lastReceivedEngineTime;
216 #ifdef LCD_TIME_SYNC_OPT
217 }
218 #endif
219
220 if ( timediff > (int)(ENGINETIME_MAX - *engine_time) ) {
221 *engine_time = (timediff - (ENGINETIME_MAX - *engine_time));
222
223 /* FIX -- move this check up... should not change anything
224 * if engineboot is already locked. ???
225 */
226 if (*engineboot < ENGINEBOOT_MAX) {
227 *engineboot += 1;
228 }
229
230 } else {
231 *engine_time += timediff;
232 }
233
234 DEBUGMSGTL(("lcd_get_enginetime", "engineID "));
235 DEBUGMSGHEX(("lcd_get_enginetime", engineID, engineID_len));
236 DEBUGMSG(("lcd_get_enginetime", ": boots=%d, time=%d\n", *engineboot,
237 *engine_time));
238
239 get_enginetime_quit:
240 return rval;
241
242 } /* end get_enginetime() */
243
244 /*******************************************************************-o-******
245 * get_enginetime
246 *
247 * Parameters:
248 * *engineID
249 * engineID_len
250 * *engineboot
251 * *engine_time
252 *
253 * Returns:
254 * SNMPERR_SUCCESS Success -- when a record for engineID is found.
255 * SNMPERR_GENERR Otherwise.
256 *
257 *
258 * Lookup engineID and return the recorded values for the
259 * <engine_time, engineboot> tuple adjusted to reflect the estimated time
260 * at the engine in question.
261 *
262 * Special case: if engineID is NULL or if engineID_len is 0 then
263 * the time tuple is returned immediately as zero.
264 *
265 * XXX What if timediff wraps? >shrug<
266 * XXX Then: you need to increment the boots value. Now. Detecting
267 * this is another matter.
268 */
269 int
270 get_enginetime_ex( u_char *engineID,
271 u_int engineID_len,
272 u_int *engineboot,
273 u_int *engine_time,
274 u_int *last_engine_time,
275 u_int authenticated)
276 {
277 int rval = SNMPERR_SUCCESS;
278 time_t timediff = 0;
279 Enginetime e = NULL;
280
281
282
283 /*
284 * Sanity check.
285 */
286 if ( !engine_time || !engineboot || !last_engine_time) {
287 QUITFUN(SNMPERR_GENERR, get_enginetime_ex_quit);
288 }
289
290
291 /*
292 * Compute estimated current engine_time tuple at engineID if
293 * a record is cached for it.
294 */
295 *last_engine_time = *engine_time = *engineboot = 0;
296
297 if ( !engineID || (engineID_len<=0) ) {
298 QUITFUN(SNMPERR_GENERR, get_enginetime_ex_quit);
299 }
300
301 if ( !(e = search_enginetime_list(engineID, engineID_len)) ) {
302 QUITFUN(SNMPERR_GENERR, get_enginetime_ex_quit);
303 }
304
305 #ifdef LCD_TIME_SYNC_OPT
306 if (!authenticated || e->authenticatedFlag) {
307 #endif
308 *last_engine_time = *engine_time = e->engineTime;
309 *engineboot = e->engineBoot;
310
311 timediff = time(NULL) - e->lastReceivedEngineTime;
312 #ifdef LCD_TIME_SYNC_OPT
313 }
314 #endif
315
316 if ( timediff > (int)(ENGINETIME_MAX - *engine_time) ) {
317 *engine_time = (timediff - (ENGINETIME_MAX - *engine_time));
318
319 /* FIX -- move this check up... should not change anything
320 * if engineboot is already locked. ???
321 */
322 if (*engineboot < ENGINEBOOT_MAX) {
323 *engineboot += 1;
324 }
325
326 } else {
327 *engine_time += timediff;
328 }
329
330 DEBUGMSGTL(("lcd_get_enginetime_ex", "engineID "));
331 DEBUGMSGHEX(("lcd_get_enginetime_ex", engineID, engineID_len));
332 DEBUGMSG(("lcd_get_enginetime_ex", ": boots=%d, time=%d\n", *engineboot,
333 *engine_time));
334
335 get_enginetime_ex_quit:
336 return rval;
337
338 } /* end get_enginetime_ex() */
339
340
341
342
343 /*******************************************************************-o-******
344 * set_enginetime
345 *
346 * Parameters:
347 * *engineID
348 * engineID_len
349 * engineboot
350 * engine_time
351 *
352 * Returns:
353 * SNMPERR_SUCCESS Success.
354 * SNMPERR_GENERR Otherwise.
355 *
356 *
357 * Lookup engineID and store the given <engine_time, engineboot> tuple
358 * and then stamp the record with a consistent source of local time.
359 * If the engineID record does not exist, create one.
360 *
361 * Special case: engineID is NULL or engineID_len is 0 defines an engineID
362 * that is "always set."
363 *
364 * XXX "Current time within the local engine" == time(NULL)...
365 */
366 int
367 set_enginetime( u_char *engineID,
368 u_int engineID_len,
369 u_int engineboot,
370 u_int engine_time,
371 u_int authenticated)
372 {
373 int rval = SNMPERR_SUCCESS,
374 iindex;
375 Enginetime e = NULL;
376
377
378
379 /*
380 * Sanity check.
381 */
382 if ( !engineID || (engineID_len <= 0) ) {
383 return rval;
384 }
385
386
387 /*
388 * Store the given <engine_time, engineboot> tuple in the record
389 * for engineID. Create a new record if necessary.
390 */
391 if ( !(e = search_enginetime_list(engineID, engineID_len)) )
392 {
393 if ( (iindex = hash_engineID(engineID, engineID_len)) < 0 )
394 {
395 QUITFUN(SNMPERR_GENERR, set_enginetime_quit);
396 }
397
398 e = (Enginetime) calloc(1,sizeof(*e));
399
400 e->next = etimelist[iindex];
401 etimelist[iindex] = e;
402
403 e->engineID = (u_char *) calloc(1,engineID_len);
404 memcpy(e->engineID, engineID, engineID_len);
405
406 e->engineID_len = engineID_len;
407 }
408 #ifdef LCD_TIME_SYNC_OPT
409 if (authenticated || !e->authenticatedFlag) {
410 e->authenticatedFlag = authenticated;
411 #else
412 if (authenticated) {
413 #endif
414 e->engineTime = engine_time;
415 e->engineBoot = engineboot;
416 e->lastReceivedEngineTime = time(NULL);
417 }
418
419 e = NULL; /* Indicates a successful update. */
420
421 DEBUGMSGTL(("lcd_set_enginetime", "engineID "));
422 DEBUGMSGHEX(("lcd_set_enginetime", engineID, engineID_len));
423 DEBUGMSG(("lcd_set_enginetime", ": boots=%d, time=%d\n", engineboot,
424 engine_time));
425
426 set_enginetime_quit:
427 SNMP_FREE(e);
428
429 return rval;
430
431 } /* end set_enginetime() */
432
433
434
435
436 /*******************************************************************-o-******
437 * search_enginetime_list
438 *
439 * Parameters:
440 * *engineID
441 * engineID_len
442 *
443 * Returns:
444 * Pointer to a etimelist record with engineID <engineID> -OR-
445 * NULL if no record exists.
446 *
447 *
448 * Search etimelist for an entry with engineID.
449 *
450 * ASSUMES that no engineID will have more than one record in the list.
451 */
452 Enginetime
453 search_enginetime_list(u_char *engineID, u_int engineID_len)
454 {
455 int rval = SNMPERR_SUCCESS;
456 Enginetime e = NULL;
457
458
459 /*
460 * Sanity check.
461 */
462 if ( !engineID || (engineID_len<=0) ) {
463 QUITFUN(SNMPERR_GENERR, search_enginetime_list_quit);
464 }
465
466
467 /*
468 * Find the entry for engineID if there be one.
469 */
470 rval = hash_engineID(engineID, engineID_len);
471 if (rval < 0) {
472 QUITFUN(SNMPERR_GENERR, search_enginetime_list_quit);
473 }
474 e = etimelist[rval];
475
476 for ( /*EMPTY*/; e; e = e->next )
477 {
478 if ( (engineID_len == e->engineID_len)
479 && !memcmp(e->engineID, engineID, engineID_len) )
480 {
481 break;
482 }
483 }
484
485
486 search_enginetime_list_quit:
487 return e;
488
489 } /* end search_enginetime_list() */
490
491
492
493
494
495 /*******************************************************************-o-******
496 * hash_engineID
497 *
498 * Parameters:
499 * *engineID
500 * engineID_len
501 *
502 * Returns:
503 * >0 etimelist index for this engineID.
504 * SNMPERR_GENERR Error.
505 *
506 *
507 * Use a cheap hash to build an index into the etimelist. Method is
508 * to hash the engineID, then split the hash into u_int's and add them up
509 * and modulo the size of the list.
510 *
511 */
512 int
513 hash_engineID(u_char *engineID, u_int engineID_len)
514 {
515 int rval = SNMPERR_GENERR;
516 size_t buf_len = SNMP_MAXBUF;
517 u_int additive = 0;
518 u_char *bufp,
519 buf[SNMP_MAXBUF];
520 void *context = NULL;
521
522
523
524 /*
525 * Sanity check.
526 */
527 if ( !engineID || (engineID_len <= 0) ) {
528 QUITFUN(SNMPERR_GENERR, hash_engineID_quit);
529 }
530
531
532 /*
533 * Hash engineID into a list index.
534 */
535 rval = sc_hash(usmHMACMD5AuthProtocol,
536 sizeof(usmHMACMD5AuthProtocol)/sizeof(oid),
537 engineID, engineID_len,
538 buf, &buf_len);
539 QUITFUN(rval, hash_engineID_quit);
540
541 for ( bufp = buf; (bufp-buf) < (int)buf_len; bufp += 4 ) {
542 additive += (u_int) *bufp;
543 }
544
545 hash_engineID_quit:
546 SNMP_FREE(context);
547 memset(buf, 0, SNMP_MAXBUF);
548
549 return (rval < 0) ? rval : (additive % ETIMELIST_SIZE);
550
551 } /* end hash_engineID() */
552
553
554
555
556 #ifdef SNMP_TESTING_CODE
557 /*******************************************************************-o-******
558 * dump_etimelist_entry
559 *
560 * Parameters:
561 * e
562 * count
563 */
564 void
565 dump_etimelist_entry(Enginetime e, int count)
566 {
567 u_int buflen;
568 char tabs[SNMP_MAXBUF],
569 *t = tabs,
570 *s;
571
572
573
574 count += 1;
575 while (count--) {
576 t += sprintf(t, " ");
577 }
578
579
580 buflen = e->engineID_len;
581 #ifdef SNMP_TESTING_CODE
582 if ( !(s = dump_snmpEngineID(e->engineID, &buflen)) ) {
583 #endif
584 binary_to_hex(e->engineID, e->engineID_len, &s);
585 #ifdef SNMP_TESTING_CODE
586 }
587 #endif
588
589 DEBUGMSGTL(("dump_etimelist", "%s\n",tabs));
590 DEBUGMSGTL(("dump_etimelist", "%s%s (len=%d) <%d,%d>\n", tabs,
591 s, e->engineID_len,
592 e->engineTime, e->engineBoot));
593 DEBUGMSGTL(("dump_etimelist", "%s%ld (%ld) -- %s", tabs,
594 e->lastReceivedEngineTime,
595 time(NULL) - e->lastReceivedEngineTime,
596 ctime(&e->lastReceivedEngineTime)));
597
598 SNMP_FREE(s);
599
600 } /* end dump_etimelist_entry() */
601
602
603
604
605 /*******************************************************************-o-******
606 * dump_etimelist
607 */
608 void
609 dump_etimelist(void)
610 {
611 int iindex = -1,
612 count = 0;
613 Enginetime e;
614
615
616
617 DEBUGMSGTL(("dump_etimelist", "\n"));
618
619 while (++iindex < ETIMELIST_SIZE) {
620 DEBUGMSG(("dump_etimelist", "[%d]", iindex));
621
622 count = 0;
623 e = etimelist[iindex];
624
625 while (e) {
626 dump_etimelist_entry(e, count++);
627 e = e->next;
628 }
629
630 if (count > 0) {
631 DEBUGMSG(("dump_etimelist", "\n"));
632 }
633 } /* endwhile */
634
635 DEBUGMSG(("dump_etimelist", "\n"));
636
637 } /* end dump_etimelist() */
638 #endif /* SNMP_TESTING_CODE */