1 /* $NetBSD: clocktime.c,v 1.1.1.1 2009/12/13 16:55:02 kardel Exp $ */ 2 3 /* 4 * clocktime - compute the NTP date from a day of year, hour, minute 5 * and second. 6 */ 7 #include "ntp_fp.h" 8 #include "ntp_unixtime.h" 9 #include "ntp_stdlib.h" 10 11 /* 12 * Hacks to avoid excercising the multiplier. I have no pride. 13 */ 14 #define MULBY10(x) (((x)<<3) + ((x)<<1)) 15 #define MULBY60(x) (((x)<<6) - ((x)<<2)) /* watch overflow */ 16 #define MULBY24(x) (((x)<<4) + ((x)<<3)) 17 18 /* 19 * Two days, in seconds. 20 */ 21 #define TWODAYS (2*24*60*60) 22 23 /* 24 * We demand that the time be within CLOSETIME seconds of the receive 25 * time stamp. This is about 4 hours, which hopefully should be 26 * wide enough to collect most data, while close enough to keep things 27 * from getting confused. 28 */ 29 #define CLOSETIME (4*60*60) 30 31 32 int 33 clocktime( 34 int yday, 35 int hour, 36 int minute, 37 int second, 38 int tzoff, 39 u_long rec_ui, 40 u_long *yearstart, 41 u_int32 *ts_ui 42 ) 43 { 44 register long tmp; 45 register u_long date; 46 register u_long yst; 47 48 /* 49 * Compute the offset into the year in seconds. Note that 50 * this could come out to be a negative number. 51 */ 52 tmp = (long)(MULBY24((yday-1)) + hour + tzoff); 53 tmp = MULBY60(tmp) + (long)minute; 54 tmp = MULBY60(tmp) + (long)second; 55 56 /* 57 * Initialize yearstart, if necessary. 58 */ 59 yst = *yearstart; 60 if (yst == 0) { 61 yst = calyearstart(rec_ui); 62 *yearstart = yst; 63 } 64 65 /* 66 * Now the fun begins. We demand that the received clock time 67 * be within CLOSETIME of the receive timestamp, but 68 * there is uncertainty about the year the timestamp is in. 69 * Use the current year start for the first check, this should 70 * work most of the time. 71 */ 72 date = (u_long)(tmp + (long)yst); 73 if (date < (rec_ui + CLOSETIME) && 74 date > (rec_ui - CLOSETIME)) { 75 *ts_ui = date; 76 return 1; 77 } 78 79 /* 80 * Trouble. Next check is to see if the year rolled over and, if 81 * so, try again with the new year's start. 82 */ 83 yst = calyearstart(rec_ui); 84 if (yst != *yearstart) { 85 date = (u_long)((long)yst + tmp); 86 *ts_ui = date; 87 if (date < (rec_ui + CLOSETIME) && 88 date > (rec_ui - CLOSETIME)) { 89 *yearstart = yst; 90 return 1; 91 } 92 } 93 94 /* 95 * Here we know the year start matches the current system 96 * time. One remaining possibility is that the time code 97 * is in the year previous to that of the system time. This 98 * is only worth checking if the receive timestamp is less 99 * than a couple of days into the new year. 100 */ 101 if ((rec_ui - yst) < TWODAYS) { 102 yst = calyearstart(yst - TWODAYS); 103 if (yst != *yearstart) { 104 date = (u_long)(tmp + (long)yst); 105 if (date < (rec_ui + CLOSETIME) && 106 date > (rec_ui - CLOSETIME)) { 107 *yearstart = yst; 108 *ts_ui = date; 109 return 1; 110 } 111 } 112 } 113 114 /* 115 * One last possibility is that the time stamp is in the year 116 * following the year the system is in. Try this one before 117 * giving up. 118 */ 119 yst = calyearstart(rec_ui + TWODAYS); 120 if (yst != *yearstart) { 121 date = (u_long)((long)yst + tmp); 122 if (date < (rec_ui + CLOSETIME) && 123 date > (rec_ui - CLOSETIME)) { 124 *yearstart = yst; 125 *ts_ui = date; 126 return 1; 127 } 128 } 129 130 /* 131 * Give it up. 132 */ 133 return 0; 134 } 135