📄 ntpclient.c
字号:
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.%.6u\n", reftime.coarse, USEC(reftime.fine)); printf("(sent) %u.%.6u\n", ntpc->time_of_send[0], USEC(ntpc->time_of_send[1])); printf("Originate %u.%.6u\n", orgtime.coarse, USEC(orgtime.fine)); printf("Receive %u.%.6u\n", rectime.coarse, USEC(rectime.fine)); printf("Transmit %u.%.6u\n", xmttime.coarse, USEC(xmttime.fine)); printf("Our recv %u.%.6u\n", arrival->coarse, USEC(arrival->fine)); } el_time=ntpdiff(&orgtime,arrival); /* elapsed */ st_time=ntpdiff(&rectime,&xmttime); /* stall */ 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", el_time, st_time, el_time-st_time); printf("Skew: %9.2f\n" "Frequency: %9d\n" " day second elapsed stall skew dispersion freq\n", (skew1-skew2)/2, freq); } /* error checking, see RFC-4330 section 5 */#ifdef ENABLE_DEBUG#define FAIL(x) do { drop_reason=(x); goto fail;} while (0)#else#define FAIL(x) goto fail;#endif if (ntpc->cross_check) { if (li == 3) FAIL("LI==3"); /* unsynchronized */ if (vn < 3) FAIL("VN<3"); /* RFC-4330 documents SNTP v4, but we interoperate with NTP v3 */ if (mode != 4) FAIL("MODE!=3"); if (orgtime.coarse != ntpc->time_of_send[0] || orgtime.fine != ntpc->time_of_send[1] ) FAIL("ORG!=sent"); if (xmttime.coarse == 0 && xmttime.fine == 0) FAIL("XMT==0"); if (delay > 65536 || delay < -65536) FAIL("abs(DELAY)>65536"); if (disp > 65536 || disp < -65536) FAIL("abs(DISP)>65536"); if (stratum == 0) FAIL("STRATUM==0"); /* kiss o' death */#undef FAIL } /* XXX should I do this if debug flag is set? */ if (ntpc->set_clock) { /* you'd better be root, or ntpclient will crash! */ set_time(&xmttime); } /* Not the ideal order for printing, but we want to be sure * to do all the time-sensitive thinking (and time setting) * before we start the output, especially fflush() (which * could be slow). Of course, if debug is turned on, speed * has gone down the drain anyway. */ if (ntpc->live) { int new_freq; new_freq = contemplate_data(arrival->coarse, (skew1-skew2)/2, el_time+sec2u(disp), freq); if (!debug && new_freq != freq) set_freq(new_freq); } printf("%d %.5d.%.3d %8.1f %8.1f %8.1f %8.1f %9d\n", arrival->coarse/86400, arrival->coarse%86400, arrival->fine/4294967, el_time, st_time, (skew1-skew2)/2, sec2u(disp), freq); fflush(stdout); *error = el_time-st_time; return 0;fail:#ifdef ENABLE_DEBUG printf("%d %.5d.%.3d rejected packet: %s\n", arrival->coarse/86400, arrival->coarse%86400, arrival->fine/4294967, drop_reason);#else printf("%d %.5d.%.3d rejected packet\n", arrival->coarse/86400, arrival->coarse%86400, arrival->fine/4294967);#endif return 1;}static void stuff_net_addr(struct in_addr *p, char *hostname){ struct hostent *ntpserver; ntpserver=gethostbyname(hostname); if (ntpserver == NULL) { herror(hostname); exit(1); } if (ntpserver->h_length != 4) { /* IPv4 only, until I get a chance to test IPv6 */ fprintf(stderr,"oops %d\n",ntpserver->h_length); exit(1); } memcpy(&(p->s_addr),ntpserver->h_addr_list[0],4);}static void setup_receive(int usd, unsigned int interface, short port){ struct sockaddr_in sa_rcvr; memset(&sa_rcvr,0,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) { perror("bind"); fprintf(stderr,"could not bind to udp port %d\n",port); exit(1); } /* listen(usd,3); this isn't TCP; thanks Alexander! */}static void setup_transmit(int usd, char *host, short port, struct ntp_control *ntpc){ struct sockaddr_in sa_dest; memset(&sa_dest,0,sizeof sa_dest); sa_dest.sin_family=AF_INET; stuff_net_addr(&(sa_dest.sin_addr),host); memcpy(ntpc->serv_addr,&(sa_dest.sin_addr),4); /* XXX asumes IPv4 */ sa_dest.sin_port=htons(port); if (connect(usd,(struct sockaddr *)&sa_dest,sizeof sa_dest)==-1) {perror("connect");exit(1);}}static void primary_loop(int usd, struct ntp_control *ntpc){ fd_set fds; struct sockaddr sa_xmit; int i, pack_len, probes_sent, error; unsigned int sa_xmit_len; struct timeval to; struct ntptime udp_arrival_ntp; static u32 incoming_word[325];#define incoming ((char *) incoming_word)#define sizeof_incoming (sizeof incoming_word) if (debug) printf("Listening...\n"); probes_sent=0; sa_xmit_len=sizeof sa_xmit; to.tv_sec=0; to.tv_usec=0; for (;;) { FD_ZERO(&fds); FD_SET(usd,&fds); i=select(usd+1,&fds,NULL,NULL,&to); /* Wait on read or error */ if ((i!=1)||(!FD_ISSET(usd,&fds))) { if (i<0) { if (errno != EINTR) perror("select"); continue; } if (to.tv_sec == 0) { if (probes_sent >= ntpc->probe_count && ntpc->probe_count != 0) break; send_packet(usd,ntpc->time_of_send); ++probes_sent; to.tv_sec=ntpc->cycle_time; to.tv_usec=0; } continue; } pack_len=recvfrom(usd,incoming,sizeof_incoming,0, &sa_xmit,&sa_xmit_len); error = ntpc->goodness; if (pack_len<0) { perror("recvfrom"); } else if (pack_len>0 && (unsigned)pack_len<sizeof_incoming){ get_packet_timestamp(usd, &udp_arrival_ntp); if (check_source(pack_len, &sa_xmit, sa_xmit_len, ntpc)!=0) continue; if (rfc1305print(incoming_word, &udp_arrival_ntp, ntpc, &error)!=0) continue; /* udp_handle(usd,incoming,pack_len,&sa_xmit,sa_xmit_len); */ } else { printf("Ooops. pack_len=%d\n",pack_len); fflush(stdout); } /* best rollover option: specify -g, -s, and -l. * simpler rollover option: specify -s and -l, which * triggers a magic -c 1 */ if (( error < ntpc->goodness && ntpc->goodness != 0 ) || (probes_sent >= ntpc->probe_count && ntpc->probe_count != 0)) { ntpc->set_clock = 0; if (!ntpc->live) break; } }#undef incoming#undef sizeof_incoming}#ifdef ENABLE_REPLAYstatic void do_replay(void){ char line[100]; int n, day, freq, absolute; float sec, el_time, st_time, 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, &el_time, &st_time, &skew, &disp, &freq); if (n==7) { fputs(line,stdout); absolute=day*86400+(int)sec; errorbar=el_time+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); } }}#endifstatic void usage(char *argv0){ fprintf(stderr, "Usage: %s [-c count]"#ifdef ENABLE_DEBUG " [-d]"#endif " [-f frequency] [-g goodness] -h hostname\n" "\t[-i interval] [-l] [-p port] [-q min_delay]"#ifdef ENABLE_REPLAY " [-r]"#endif " [-s] [-t]\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 */ char *hostname=NULL; /* must be set */ int initial_freq; /* initial freq value to use */ struct ntp_control ntpc; ntpc.live=0; ntpc.set_clock=0; ntpc.probe_count=0; /* default of 0 means loop forever */ ntpc.cycle_time=600; /* seconds */ ntpc.goodness=0; ntpc.cross_check=1; for (;;) { c = getopt( argc, argv, "c:" DEBUG_OPTION "f:g:h:i:lp:q:" REPLAY_OPTION "st"); if (c == EOF) break; switch (c) { case 'c': ntpc.probe_count = atoi(optarg); break;#ifdef ENABLE_DEBUG case 'd': ++debug; break;#endif case 'f': initial_freq = atoi(optarg); if (debug) printf("initial frequency %d\n", initial_freq); set_freq(initial_freq); break; case 'g': ntpc.goodness = atoi(optarg); break; case 'h': hostname = optarg; break; case 'i': ntpc.cycle_time = atoi(optarg); break; case 'l': (ntpc.live)++; break; case 'p': udp_local_port = atoi(optarg); break; case 'q': min_delay = atof(optarg); break;#ifdef ENABLE_REPLAY case 'r': do_replay(); exit(0); break;#endif case 's': (ntpc.set_clock)++; break; case 't': (ntpc.cross_check)=0; break; default: usage(argv[0]); exit(1); } } if (hostname == NULL) { usage(argv[0]); exit(1); } if (ntpc.set_clock && !ntpc.live && !ntpc.goodness && !ntpc.probe_count) { ntpc.probe_count = 1; } /* respect only applicable MUST of RFC-4330 */ if (ntpc.probe_count != 1 && ntpc.cycle_time < MIN_INTERVAL) { ntpc.cycle_time=MIN_INTERVAL; } if (debug) { printf("Configuration:\n" " -c probe_count %d\n" " -d (debug) %d\n" " -g goodness %d\n" " -h hostname %s\n" " -i interval %d\n" " -l live %d\n" " -p local_port %d\n" " -q min_delay %f\n" " -s set_clock %d\n" " -x cross_check %d\n", ntpc.probe_count, debug, ntpc.goodness, hostname, ntpc.cycle_time, ntpc.live, udp_local_port, min_delay, ntpc.set_clock, ntpc.cross_check ); } /* Startup sequence */ if ((usd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==-1) {perror ("socket");exit(1);} setup_receive(usd, INADDR_ANY, udp_local_port); setup_transmit(usd, hostname, NTP_PORT, &ntpc); primary_loop(usd, &ntpc); close(usd); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -