📄 main.c
字号:
k = 1; }/* Count the number of rejected packets and fail if there are too many. */ if (k) { ++rejects; if (++rej_level > count) fatal(0,"too many bad or lost packets",NULL); else { retry = 1; continue; } } else retry = 0; if ((rej_level -= (count < 5 ? count : 5)) < 0) rej_level = 0; if (verbose > 2) fprintf(stderr,"Offset=%.6f+/-%.6f @ %.6f disp=%.6f\n", offset,error,when,dispersion); } /* Calculate the statistics, and display the results or make the initialcorrection. Note that estimate_stats() will return zero if a timestampindicates synchronisation loss (usually due to down time or a change of server,somewhere upstream), and that the recovery operation is unstructured, so greatcare should be taken when modifying it. Also, we want to clear the saved stateis the statistics are bad. */ handle_saving(save_clear,&total,&index,&cycle,record,&previous,&when, &correction); ++accepts; dispersion = data.dispersion; previous = when = estimate_stats(&total,&index,record,correction,&dispersion, &when,&offset,&error,&drift,&drifterr,&waiting,1); if (verbose > 2) { fprintf(stderr,"tot=%d ind=%d dis=%.3f when=%.3f off=%.3f ", total,index,dispersion,when,offset); fprintf(stderr,"err=%.3f wait=%d\n",error,waiting); } if (when == 0.0) return; x = (maxoff < 0.0 ? -maxoff : maxoff); if ((offset < 0.0 ? -offset : offset) > x) maxoff = offset; correction = 0.0; if (operation == op_client || accepts >= count) { if (action == action_display) { format_time(text,100,offset,error,drift,drifterr); printf("%s\n",text); } else { x = reset_clock(offset,error,1); correction += x; offset -= x; } } else waiting = delay; handle_saving(save_write,&total,&index,&cycle,record,&previous,&when, &correction);/* Now correct the clock for a while, before getting another packet andupdating the statistics. */ while (when < previous+delay-waiting) { do_nothing(waiting); if (action == action_display) when += waiting; else { correction += correct_drift(&when,&offset,drift); handle_saving(save_write,&total,&index,&cycle,record, &previous,&when,&correction); } }continue1: ; }}int run_client (char *hostnames[], int nhosts, double *server_offset) {/* Get enough responses to do something with; or not, as the case may be. Notethat it allows for half of the packets to be bad, so may make up to twice asmany attempts as specified by the -c value. The deadline checking is merelyparanoia, to protect against broken signal handling - it cannot easily betriggered if the signal handling works.This call differs in libmsntp from normal msntp in that it returns the offsetbetween the local time and the server's time, as seconds, with a fractionalpart.*/ double history[COUNT_MAX], guesses[COUNT_MAX], offset, error, deadline, a, b, x, y; int accepts = 0, rejects = 0, flushes = 0, replicates = 0, cycle = 0, k, ret; unsigned char transmit[NTP_PACKET_MIN]; ntp_data data; char text[100]; if (verbose > 2) { format_time(text,50,0.0,-1.0,0.0,-1.0); fprintf(stderr,"Started=%.6f %s\n",current_time(JAN_1970),text); } for (k = 0; k < nhosts; ++k) open_socket(k,hostnames[k],delay); if (action != action_display) { set_lock(1); locked = 1; } attempts = 0; deadline = current_time(JAN_1970)+delay;/* Listen to broadcast packets and select the best (i.e. earliest). This willbe sensitive to a bad NTP broadcaster, but I believe such things are very rarein practice. In any case, if you have one, it is probably the only one on yoursubnet, so you are knackered! This allows up to ETHERNET_MAX replications perpacket, for systems with multiple addresses for receiving broadcasts; the onlyreason for a limit is to protect against broken NTP servers always returningthe same time. */ if (operation == op_listen) { while (accepts < count) { if (current_time(JAN_1970) > deadline) { fatal(EMSNTP_UNKNOWN, "not enough valid broadcasts received in time",NULL); return EMSNTP_UNKNOWN; } if (ret = flush_socket(0, &k)) return ret; flushes += k; if (read_packet(0,&data,&x,&y)) { if (++rejects > count) { fatal(EMSNTP_UNKNOWN,"too many bad or lost packets",NULL); return EMSNTP_UNKNOWN; } else continue; } else { a = data.transmit; for (k = 0; k < accepts; ++k) if (a == history[k]) { if (++replicates > ETHERNET_MAX*count) { fatal(EMSNTP_UNKNOWN, "too many replicated packets",NULL); return EMSNTP_UNKNOWN; } goto continue1; } history[accepts] = a; guesses[accepts++] = x; } if (verbose > 2) fprintf(stderr,"Offset=%.6f disp=%.6f\n",x,dispersion); else if (verbose > 1) fprintf(stderr,"%s: offset=%.3f disp=%.3f\n", argv0,x,dispersion);/* Note that bubblesort IS a good method for this amount of data. */ for (k = accepts-2; k >= 0; --k) if (guesses[k] < guesses[k+1]) break; else { x = guesses[k]; guesses[k] = guesses[k+1]; guesses[k+1] = x; }continue1: ; } offset = guesses[0]; error = minerr+guesses[count <= 5 ? count-1 : 5]-offset; if (verbose > 2) fprintf(stderr,"accepts=%d rejects=%d flushes=%d replicates=%d\n", accepts,rejects,flushes,replicates);/* Handle the client/server model. It keeps a record of transmitted times,mainly out of paranoia. */ } else { offset = 0.0; error = NTP_INSANITY; while (accepts < count && attempts < 2*count) { if (current_time(JAN_1970) > deadline) { fatal(EMSNTP_TOO_FEW_RESPONSES, "not enough valid responses received in time",NULL); return EMSNTP_TOO_FEW_RESPONSES; } make_packet(&data,NTP_CLIENT); outgoing[attempts++] = data.transmit; if (verbose > 2) { fprintf(stderr,"Outgoing packet on socket %d:\n",cycle); display_data(&data); } pack_ntp(transmit,NTP_PACKET_MIN,&data); if (verbose > 2) display_packet(transmit,NTP_PACKET_MIN); if (ret = flush_socket(cycle, &k)) return ret; flushes += k; write_socket(cycle,transmit,NTP_PACKET_MIN); if (read_packet(cycle,&data,&x,&y)) { if (++rejects > count) { fatal(EMSNTP_BAD_RESPONSES, "too many bad or lost packets",NULL); return EMSNTP_BAD_RESPONSES; } else continue; } else ++accepts; if (++cycle >= nhosts) cycle = 0;/* Work out the most accurate time, and check that it isn't more accurate thanthe results warrant. */ if (verbose > 2) fprintf(stderr,"Offset=%.6f+/-%.6f disp=%.6f\n",x,y,dispersion); else if (verbose > 1) fprintf(stderr,"%s: offset=%.3f+/-%.3f disp=%.3f\n", argv0,x,y,dispersion); if ((a = x-offset) < 0.0) a = -a; if (accepts <= 1) a = 0.0; b = error+y; if (y < error) { offset = x; error = y; } if (verbose > 2) fprintf(stderr,"best=%.6f+/-%.6f\n",offset,error); if (a > b) { sprintf(text,"%d",cycle); fatal(0,"inconsistent times got from NTP server on socket %s", text); return EMSNTP_NTP_INCONSISTENCY; } if (error <= minerr) break; } if (verbose > 2) fprintf(stderr,"accepts=%d rejects=%d flushes=%d\n", accepts,rejects,flushes); }/* Tidy up the socket, issues diagnostics and perform the action. */ for (k = 0; k < nhosts; ++k) close_socket(k); if (accepts == 0) { fatal(EMSNTP_NO_GOOD_RESPONSE,"no acceptable packets received",NULL); return EMSNTP_NO_GOOD_RESPONSE; } if (error > NTP_INSANITY) { fatal(EMSNTP_NTP_INSANITY, "unable to get a reasonable time estimate",NULL); return EMSNTP_NTP_INSANITY; } if (verbose > 2) fprintf(stderr,"Correction: %.6f +/- %.6f disp=%.6f\n", offset,error,dispersion); if (action == action_display) { format_time(text,75,offset,error,0.0,-1.0); printf("%s\n",text); } else (void)reset_clock(offset,error,0); if (locked) set_lock(0); if (verbose > 2) fprintf(stderr,"Stopped normally\n"); *server_offset = offset; return 0;}int msntp_main (int argc, char *argv[]) {/* This is the entry point and all that. It decodes the arguments and callsone of the specialised routines to do the work. */ char *hostnames[MAX_SOCKETS], *savename = NULL; int daemon = 0, nhosts = 0, help = 0, args = argc-1, k; char c; double offset; if (argv[0] == NULL || argv[0][0] == '\0') argv0 = "msntp"; else if ((argv0 = strrchr(argv[0],'/')) != NULL) ++argv0; else argv0 = argv[0]; setvbuf(stdout,NULL,_IOLBF,BUFSIZ); setvbuf(stderr,NULL,_IOLBF,BUFSIZ); if (INT_MAX < 2147483647) fatal(0,"msntp requires >= 32-bit ints",NULL); if (DBL_EPSILON > 1.0e-13) fatal(0,"msntp requires doubles with eps <= 1.0e-13",NULL); for (k = 0; k < MAX_SOCKETS; ++k) hostnames[k] = NULL;/* Decode the arguments. */ while (argc > 1) { k = 1; if (strcmp(argv[1],"-B") == 0 && action == 0) { action = action_broadcast; if (argc > 2) { if (sscanf(argv[2],"%d%c",&period,&c) != 1) syntax(1); if (period < 1 || period > 1440) fatal(0,"%s option value out of range","-B"); period *= 60; k = 2; } else period = 60*60; } else if (strcmp(argv[1],"-S") == 0 && action == 0) action = action_server; else if (strcmp(argv[1],"-q") == 0 && action == 0) action = action_query; else if (strcmp(argv[1],"-r") == 0 && action == 0) action = action_reset; else if (strcmp(argv[1],"-a") == 0 && action == 0) action = action_adjust; else if (strcmp(argv[1],"-l") == 0 && lockname == NULL && argc > 2) { lockname = argv[2]; k = 2; } else if ((strcmp(argv[1],"-x") == 0) && daemon == 0) { if (argc > 2 && sscanf(argv[2],"%d%c",&daemon,&c) == 1) { if (daemon < 1 || daemon > 1440) fatal(0,"%s option value out of range",argv[1]); k = 2; } else daemon = 300; } else if (strcmp(argv[1],"-f") == 0 && savename == NULL && argc > 2) { savename = argv[2]; k = 2; } else if ((strcmp(argv[1],"--help") == 0 || strcmp(argv[1],"-h") == 0 || strcmp(argv[1],"-?") == 0) && help == 0) help = 1; else if (strcmp(argv[1],"-v") == 0 && verbose == 0) v
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -