📄 ntptimeset.c
字号:
* Make sure the server is at least somewhat sane. If not, ignore * it for later. */ if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) { if (debug > 1) printf("receive: pkt insane\n"); return; } /* * Calculate the round trip delay (di) and the clock offset (ci). * We use the equations (reordered from those in the spec): * * d = (t2 - t3) - (t1 - t0) * c = ((t2 - t3) + (t1 - t0)) / 2 */ t10 = server->org; /* pkt.xmt == t1 */ L_SUB(&t10, &rbufp->recv_time); /* recv_time == t0*/ t23 = rec; /* pkt.rec == t2 */ L_SUB(&t23, &org); /* pkt->org == t3 */ /* now have (t2 - t3) and (t0 - t1). Calculate (ci) and (di) */ ci = t10; L_ADD(&ci, &t23); L_RSHIFT(&ci); /* * Calculate di in t23 in full precision, then truncate * to an s_fp. */ L_SUB(&t23, &t10); di = LFPTOFP(&t23); if (debug > 3) printf("offset: %s, delay %s\n", lfptoa(&ci, 6), fptoa(di, 5)); di += (FP_SECOND >> (-(int)NTPDATE_PRECISION)) + (FP_SECOND >> (-(int)server->precision)) + NTP_MAXSKW; if (di <= 0) { /* value still too raunchy to use? */ L_CLR(&ci); di = 0; } else { di = max(di, NTP_MINDIST); } /* * This one is valid. Give it to clock_filter(), */ clock_filter(server, di, &ci); if (debug > 1) printf("receive from %s\n", ntoa(&rbufp->srcadr)); /* * See if we should goes the transmission. If not return now * otherwise have the next event time be shortened */ if (server->stratum <= NTP_INFIN) return; /* server does not have a stratum */ if (server->leap == LEAP_NOTINSYNC) return; /* just booted server or out of sync */ if (!L_ISHIS(&server->org, &server->reftime)) return; /* broken host */ if (server->trust != 0) return; /* can not trust it */ if (server->dispersion < DESIREDDISP) return; /* we have the desired dispersion */ server->event_time -= (TIMER_HZ+1);}/* * clock_filter - add clock sample, determine a server's delay, dispersion * and offset */static voidclock_filter( register struct server *server, s_fp di, l_fp *c ){ register int i, j; int ord[NTP_SHIFT]; /* * Insert sample and increment nextpt */ i = server->filter_nextpt; server->filter_delay[i] = di; server->filter_offset[i] = *c; server->filter_soffset[i] = LFPTOFP(c); server->filter_nextpt++; if (server->filter_nextpt >= NTP_SHIFT) server->filter_nextpt = 0; /* * Sort indices into increasing delay order */ for (i = 0; i < NTP_SHIFT; i++) ord[i] = i; for (i = 0; i < (NTP_SHIFT-1); i++) { for (j = i+1; j < NTP_SHIFT; j++) { if (server->filter_delay[ord[j]] == 0) continue; if (server->filter_delay[ord[i]] == 0 || (server->filter_delay[ord[i]] > server->filter_delay[ord[j]])) { register int tmp; tmp = ord[i]; ord[i] = ord[j]; ord[j] = tmp; } } } /* * Now compute the dispersion, and assign values to delay and * offset. If there are no samples in the register, delay and * offset go to zero and dispersion is set to the maximum. */ if (server->filter_delay[ord[0]] == 0) { server->delay = 0; L_CLR(&server->offset); server->soffset = 0; server->dispersion = PEER_MAXDISP; } else { register s_fp d; server->delay = server->filter_delay[ord[0]]; server->offset = server->filter_offset[ord[0]]; server->soffset = LFPTOFP(&server->offset); server->dispersion = 0; for (i = 1; i < NTP_SHIFT; i++) { if (server->filter_delay[ord[i]] == 0) d = PEER_MAXDISP; else { d = server->filter_soffset[ord[i]] - server->filter_soffset[ord[0]]; if (d < 0) d = -d; if (d > PEER_MAXDISP) d = PEER_MAXDISP; } /* * XXX This *knows* PEER_FILTER is 1/2 */ server->dispersion += (u_fp)(d) >> i; } } /* * We're done */}/* clock_count - count the clock sources we have */static voidclock_count(void){ register struct server *server; register int n; /* reset counts */ validcount = valid_n_low = 0; /* go through the list of servers and count the clocks we believe * and that have low dispersion */ for (n = 0; n < sys_numservers; n++) { server = sys_servers[n]; if (server->delay == 0) { continue; /* no data */ } if (server->stratum > NTP_INFIN) { continue; /* stratum no good */ } if (server->delay > NTP_MAXWGT) { continue; /* too far away */ } if (server->leap == LEAP_NOTINSYNC) continue; /* he's in trouble */ if (!L_ISHIS(&server->org, &server->reftime)) { continue; /* very broken host */ } if ((server->org.l_ui - server->reftime.l_ui) >= NTP_MAXAGE) { continue; /* too long without sync */ } if (server->trust != 0) { continue; } /* * This one is a valid time source.. */ validcount++; /* * See if this one has a okay low dispersion */ if (server->dispersion <= DESIREDDISP) valid_n_low++; } if (debug > 1) printf("have %d, valid %d, low %d\n", responding, validcount, valid_n_low);}/* * clock_select - select the pick-of-the-litter clock from the samples * we've got. */static struct server *clock_select(void){ register struct server *server; register int i; register int nlist; register s_fp d; register int j; register int n; s_fp local_threshold; struct server *server_list[NTP_MAXCLOCK]; u_fp server_badness[NTP_MAXCLOCK]; struct server *sys_server; /* * This first chunk of code is supposed to go through all * servers we know about to find the NTP_MAXLIST servers which * are most likely to succeed. We run through the list * doing the sanity checks and trying to insert anyone who * looks okay. We are at all times aware that we should * only keep samples from the top two strata and we only need * NTP_MAXLIST of them. */ nlist = 0; /* none yet */ for (n = 0; n < sys_numservers; n++) { server = sys_servers[n]; if (server->delay == 0) continue; /* no data */ if (server->stratum > NTP_INFIN) continue; /* stratum no good */ if (server->delay > NTP_MAXWGT) { continue; /* too far away */ } if (server->leap == LEAP_NOTINSYNC) continue; /* he's in trouble */ if (!L_ISHIS(&server->org, &server->reftime)) { continue; /* very broken host */ } if ((server->org.l_ui - server->reftime.l_ui) >= NTP_MAXAGE) { continue; /* too long without sync */ } if (server->trust != 0) { continue; } /* * This one seems sane. Find where he belongs * on the list. */ d = server->dispersion + server->dispersion; for (i = 0; i < nlist; i++) if (server->stratum <= server_list[i]->stratum) break; for ( ; i < nlist; i++) { if (server->stratum < server_list[i]->stratum) break; if (d < (s_fp) server_badness[i]) break; } /* * If i points past the end of the list, this * guy is a loser, else stick him in. */ if (i >= NTP_MAXLIST) continue; for (j = nlist; j > i; j--) if (j < NTP_MAXLIST) { server_list[j] = server_list[j-1]; server_badness[j] = server_badness[j-1]; } server_list[i] = server; server_badness[i] = d; if (nlist < NTP_MAXLIST) nlist++; } /* * Got the five-or-less best. Cut the list where the number of * strata exceeds two. */ j = 0; for (i = 1; i < nlist; i++) if (server_list[i]->stratum > server_list[i-1]->stratum) if (++j == 2) { nlist = i; break; } /* * Whew! What we should have by now is 0 to 5 candidates for * the job of syncing us. If we have none, we're out of luck. * If we have one, he's a winner. If we have more, do falseticker * detection. */ if (nlist == 0) sys_server = 0; else if (nlist == 1) { sys_server = server_list[0]; } else { /* * Re-sort by stratum, bdelay estimate quality and * server.delay. */ for (i = 0; i < nlist-1; i++) for (j = i+1; j < nlist; j++) { if (server_list[i]->stratum < server_list[j]->stratum) break; /* already sorted by stratum */ if (server_list[i]->delay < server_list[j]->delay) continue; server = server_list[i]; server_list[i] = server_list[j]; server_list[j] = server; } /* * Calculate the fixed part of the dispersion limit */ local_threshold = (FP_SECOND >> (-(int)NTPDATE_PRECISION)) + NTP_MAXSKW; /* * Now drop samples until we're down to one. */ while (nlist > 1) { for (n = 0; n < nlist; n++) { server_badness[n] = 0; for (j = 0; j < nlist; j++) { if (j == n) /* with self? */ continue; d = server_list[j]->soffset - server_list[n]->soffset; if (d < 0) /* absolute value */ d = -d; /* * XXX This code *knows* that * NTP_SELECT is 3/4 */ for (i = 0; i < j; i++) d = (d>>1) + (d>>2); server_badness[n] += d; } } /* * We now have an array of nlist badness * coefficients. Find the badest. Find * the minimum precision while we're at * it. */ i = 0; n = server_list[0]->precision;; for (j = 1; j < nlist; j++) { if (server_badness[j] >= server_badness[i]) i = j; if (n > server_list[j]->precision) n = server_list[j]->precision; } /* * i is the index of the server with the worst * dispersion. If his dispersion is less than * the threshold, stop now, else delete him and * continue around again. */ if (server_badness[i] < (local_threshold + (FP_SECOND >> (-n)))) break; for (j = i + 1; j < nlist; j++) server_list[j-1] = server_list[j]; nlist--; } /* * What remains is a list of less than 5 servers. Take * the best. */ sys_server = server_list[0]; } /* * That's it. Return our server. */ return sys_server;}/* * set_local_clock -- handle setting the local clock or displaying info. */static voidset_local_clock(void){ register int i; register struct server *server; time_t tmp; double dtemp; /* * if setting time then print final analysis */ if (set_time) analysis(1); /* * pick a clock */ server = clock_select(); /* * do some display of information */ if (debug || verbose) { for (i = 0; i < sys_numservers; i++) printserver(sys_servers[i], stdout); if (debug) printf("packets sent %ld, received %ld\n", total_xmit, total_recv); } /* * see if we have a server to set the time with */ if (server == 0) { if (!set_time || verbose) fprintf(stdout,"No servers available to sync time with\n"); exit(1); } /* * we have a valid and selected time to use!!!!! */ /* * if we are not setting the time then display offset and exit */ if (!set_time) { fprintf(stdout, "Your clock is off by %s seconds. (%s) [%ld/%ld]\n", lfptoa(&server->offset, 7), ntoa(&server->srcadr), total_xmit, total_recv); exit(0); } /* * set the clock * XXX: Examine the more flexible approach used by ntpdate. * Note that a design consideration here is that we sometimes * _want_ to step the clock by a _huge_ amount in either * direction, because the local clock is completely bogus. * This condition must be recognized and dealt with, so * that we always get a good time when this completes. * -- jhutz+@cmu.edu, 16-Aug-1999 */ LFPTOD(&server->offset, dtemp); step_systime(dtemp); time(&tmp); fprintf(stdout,"Time set to %.20s [%s %s %ld/%ld]\n", ctime(&tmp)+4, ntoa(&server->srcadr), lfptoa(&server->offset, 7), total_xmit, total_recv); exit(0);}/* * findserver - find a server in the list given its address */static struct server *findserver( struct sockaddr_in *addr ){ register int i; register u_int32 netnum; if (htons(addr->sin_port) != NTP_PORT) return 0; netnum = addr->sin_addr.s_addr; for (i = 0; i < sys_numservers; i++) { if (netnum == sys_servers[i]->srcadr.sin_addr.s_addr) return sys_servers[i]; } return 0;}/* * timer - process a timer interrupt */static voidtimer(void){ register int k; /* * Bump the current idea of the time */ current_time++; /* * see if we have reached half time */ if (current_time >= half_time && !secondhalf) { secondhalf++; if (debug) printf("\nSecond Half of Timeout!\n"); printmsg++; } /* * We only want to send a few packets per transmit interrupt
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -