📄 ntpclient.c
字号:
double etime,stime,skew1,skew2; int freq;#define Data(i) ntohl(((unsigned int *)data)[i]) li = Data(0) >> 30 & 0x03; vn = Data(0) >> 27 & 0x07; mode = Data(0) >> 24 & 0x07; stratum = Data(0) >> 16 & 0xff; poll = Data(0) >> 8 & 0xff; prec = Data(0) & 0xff; if (prec & 0x80) prec|=0xffffff00; delay = Data(1); disp = Data(2); refid = Data(3); reftime.coarse = Data(4); reftime.fine = Data(5); orgtime.coarse = Data(6); orgtime.fine = Data(7); rectime.coarse = Data(8); rectime.fine = Data(9); xmttime.coarse = Data(10); xmttime.fine = Data(11);#undef Data if (stratum == 0) return -1; if (set_clock) { /* you'd better be root, or ntpclient will crash! */ struct timeval tv_set; /* it would be even better to subtract half the slop */ tv_set.tv_sec = xmttime.coarse - JAN_1970; /* divide xmttime.fine by 4294.967296 */ tv_set.tv_usec = USEC(xmttime.fine); if (settimeofday(&tv_set,NULL)<0) { perror("settimeofday"); exit(1); } if (debug) { printf("set time to %lu.%.6lu\n", tv_set.tv_sec, tv_set.tv_usec); } } if (debug) { printf("LI=%d VN=%d Mode=%d Stratum=%d Poll=%d Precision=%d\n", li, vn, mode, stratum, poll, prec); printf("Delay=%.1f Dispersion=%.1f Refid=%u.%u.%u.%u\n", sec2u(delay),sec2u(disp), refid>>24&0xff, refid>>16&0xff, refid>>8&0xff, refid&0xff); printf("Reference %u.%.10u\n", reftime.coarse, reftime.fine); printf("Originate %u.%.10u\n", orgtime.coarse, orgtime.fine); printf("Receive %u.%.10u\n", rectime.coarse, rectime.fine); printf("Transmit %u.%.10u\n", xmttime.coarse, xmttime.fine); printf("Our recv %u.%.10u\n", arrival->coarse, arrival->fine); } etime=ntpdiff(&orgtime,arrival); stime=ntpdiff(&rectime,&xmttime); skew1=ntpdiff(&orgtime,&rectime); skew2=ntpdiff(&xmttime,arrival); freq=get_current_freq(); if (debug) { printf("Total elapsed: %9.2f\n" "Server stall: %9.2f\n" "Slop: %9.2f\n", etime, stime, etime-stime); printf("Skew: %9.2f\n" "Frequency: %9d\n" " day second elapsed stall skew dispersion freq\n", (skew1-skew2)/2, freq); printf("%d %5d.%.3d %8.1f %8.1f %8.1f %8.1f %9d\n", arrival->coarse/86400+15020, arrival->coarse%86400, arrival->fine/4294967, etime, stime, (skew1-skew2)/2, sec2u(disp), freq); } fflush(stdout); if (live) { int new_freq; new_freq = contemplate_data(arrival->coarse, (skew1-skew2)/2, etime+sec2u(disp), freq); if (!debug && new_freq != freq) set_freq(new_freq); } return 0;}void setup_receive(int usd, unsigned int interface, short port){ struct sockaddr_in sa_rcvr; bzero((char *) &sa_rcvr, sizeof(sa_rcvr)); sa_rcvr.sin_family=AF_INET; sa_rcvr.sin_addr.s_addr=htonl(interface); sa_rcvr.sin_port=htons(port); if(bind(usd,(struct sockaddr *) &sa_rcvr,sizeof(sa_rcvr)) == -1) { fprintf(stderr,"could not bind to udp port %d\n",port); perror("bind"); exit(1); } listen(usd,3);}void setup_transmit(int usd, char *host){ char hostname[HOSTNAME_MAX_LEN]; char *p_temp, *p_cur; p_cur = host; /*The NTP servers' ip address is divided by space*/ do { p_temp = p_cur; while((*p_cur != 0x20) && *p_cur != '\0') p_cur++; /*find the space or the end of string, copy the hostname and connect it */ if((*p_cur == 0x20) || (*p_cur == '\0')) { if(p_cur - p_temp > HOSTNAME_MAX_LEN) { printf("The hostname is too long\n"); p_cur++; continue; } memcpy(hostname, p_temp, p_cur - p_temp); hostname[p_cur - p_temp] = '\0'; host_list[host_count++] = strdup(hostname); } }while(*(p_cur++) != '\0'); /* initialize resolv.conf status */ resolv_conf_changed();}void primary_loop(int usd, int num_probes, int interval, int initial_interval){ fd_set fds; struct sockaddr_in addr; int i, pack_len, sa_xmit_len, probes_sent, next_interval; int in_startup = 1, active_polling = 1; struct timeval to; if (debug) printf("Listening...\n"); probes_sent=0; next_interval = initial_interval; send_packet(usd, 0); for (;;) { FD_ZERO(&fds); FD_SET(usd,&fds); to.tv_sec = next_interval; to.tv_usec = 0; i=select(usd+1,&fds,NULL,NULL,&to); /* Wait on read or error */ if (i<=0) { if (i<0&&errno==EINTR) continue; if (i<0) perror("select"); if (i==0) { if (probes_sent >= num_probes && num_probes != 0) break; if (in_startup) next_interval = initial_interval; else if (active_polling) { server_failed(); next_interval *= 2; if (next_interval > interval) next_interval = interval; } else { active_polling = 1; next_interval = initial_interval; } send_packet(usd, !in_startup); ++probes_sent; if (in_startup && probes_sent >= 10) in_startup = 0; } continue; } sa_xmit_len = sizeof(addr); pack_len=recvfrom(usd,incoming,sizeof(incoming),0, (struct sockaddr *)&addr,&sa_xmit_len); if (!current_addr || addr.sin_addr.s_addr != ((struct sockaddr_in *)current_addr->ai_addr) ->sin_addr.s_addr) continue; if (pack_len<0) { perror("recvfrom"); server_failed(); } else if (pack_len>0 && pack_len<sizeof(incoming)){ if (udp_handle(usd,incoming,pack_len, (struct sockaddr *)&addr, sa_xmit_len) < 0) { server_failed(); } else { in_startup = 0; active_polling = 0; next_interval = interval; } } else { printf("Ooops. pack_len=%d\n",pack_len); fflush(stdout); } if (probes_sent >= num_probes && num_probes != 0) break; }}void do_replay(void){ char line[100]; int n, day, freq, absolute; float sec, etime, stime, disp; double skew, errorbar; int simulated_freq = 0; unsigned int last_fake_time = 0; double fake_delta_time = 0.0; while (fgets(line,sizeof(line),stdin)) { n=sscanf(line,"%d %f %f %f %lf %f %d", &day, &sec, &etime, &stime, &skew, &disp, &freq); if (n==7) { fputs(line,stdout); absolute=(day-15020)*86400+(int)sec; errorbar=etime+disp; if (debug) printf("contemplate %u %.1f %.1f %d\n", absolute,skew,errorbar,freq); if (last_fake_time==0) simulated_freq=freq; fake_delta_time += (absolute-last_fake_time)*((double)(freq-simulated_freq))/65536; if (debug) printf("fake %f %d \n", fake_delta_time, simulated_freq); skew += fake_delta_time; freq = simulated_freq; last_fake_time=absolute; simulated_freq = contemplate_data(absolute, skew, errorbar, freq); } else { fprintf(stderr,"Replay input error\n"); exit(2); } }}void usage(char *argv0){ fprintf(stderr, "Usage: %s [-c count] [-d] -h hostname [-i interval] [-l]\n" "\t[-I startup_interval] [-p port] [-r] [-s] \n", argv0);}int main(int argc, char *argv[]) { int usd; /* socket */ int c; /* These parameters are settable from the command line the initializations here provide default behavior */ short int udp_local_port=0; /* default of 0 means kernel chooses */ int cycle_time=43200; /* seconds */ int initial_cycle_time=3; /* seconds */ int probe_count=0; /* default of 0 means loop forever */ /* int debug=0; is a global above */ char *hostname=NULL; /* must be set */ int replay=0; /* replay mode overrides everything */ global_argv = argv; for (;;) { c = getopt( argc, argv, "c:" DEBUG_OPTION "h:i:I:lp:rs"); if (c == EOF) break; switch (c) { case 'c': probe_count = atoi(optarg); break;#ifdef ENABLE_DEBUG case 'd': ++debug; break;#endif case 'h': hostname = optarg; break; case 'i': cycle_time = atoi(optarg); /* Don't take out this check unless you are * only querying servers that you own. */ if (cycle_time < 3600) { fprintf(stderr, "Interval of less than " "3600 is too short.\n"); exit(1); } break; case 'I': initial_cycle_time = atoi(optarg); break; case 'l': live++; break; case 'p': udp_local_port = atoi(optarg); break; case 'r': replay++; break; case 's': set_clock++; probe_count = 0; break; default: usage(argv[0]); exit(1); } }#ifdef vxworks hostname = argv[0]; set_clock++;#endif if (replay) { do_replay(); exit(0); } if (hostname == NULL) { usage(argv[0]); exit(1); } if (debug) { printf("Configuration:\n" " -c probe_count %d\n" " -d (debug) %d\n" " -h hostname %s\n" " -i interval %d\n" " -I st_interval %d\n" " -l live %d\n" " -p local_port %d\n" " -s set_clock %d\n", probe_count, debug, hostname, cycle_time, initial_cycle_time, live, udp_local_port, set_clock ); } /* Startup sequence */ if ((usd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==-1) {perror ("socket");exit(1);} fcntl(usd, F_SETFD, FD_CLOEXEC); setup_receive(usd, INADDR_ANY, udp_local_port); setup_transmit(usd, hostname); primary_loop(usd, probe_count, cycle_time, initial_cycle_time); close(usd); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -