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