ntp_proto.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,296 行 · 第 1/3 页
C
1,296 行
#ifndef lintstatic char *sccsid = "@(#)ntp_proto.c 4.1 (ULTRIX) 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1988-1990 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************/ /* *static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntp_proto.c,v $ $Revision: 3.4.1.12 $ $Date: 89/05/18 18:25:04 $"; *//* * This module actually implements the the bulk of the NTP protocol processing. * It contains a minimum of machine and operating system dependencies (or at * least that's the idea). Setup of UDP sockets, timers, etc is done in the * ntpd.c module, while arithmetic conversion routines are in ntpsubs.c *//* * $Log: ntp_proto.c,v $ * Revision 3.4.1.12 89/05/18 18:25:04 louie * Changes for reference clock feature in ntp_proto.c * * Revision 3.4.1.11 89/05/03 23:51:30 louie * Had my head on backwards with a reversed test in the clockhopper avoidance * code. Need to switch to the first selected clock when its stratum is lower * than the current sys.peer. * * Revision 3.4.1.10 89/05/03 19:03:02 louie * Stupid typo - dereferenced unused variable in select_clock() * * Revision 3.4.1.9 89/05/03 15:13:25 louie * Add code to count number of peer switches and inhibited peer switches. Clock * selection code has been updated to reflect 21 April 1989 draft of NTP spec. * * Revision 3.4.1.8 89/04/10 15:57:59 louie * New -l option for ntpd to enable logging for clock adjust messages. Changed * our idea of a bogus packet in the packet procedure to include a packet received * before a poll is sent. Fix stupid bug in delay computation having to do with * peer->precision. * * Revision 3.4.1.7 89/04/08 10:36:53 louie * The syslog message for peer selection had to be moved to account for the * anti-peer flapping code just installed. * * Revision 3.4.1.6 89/04/07 19:07:10 louie * Don't clear peer.reach register in the clear() procedure. Code to prevent * flapping between two peers with very similar dispersions. * * Revision 3.4.1.5 89/03/31 16:36:38 louie * There is now a run-time option that can be specified in the configuration * which specifies if we will synchronize to unconfigured hosts. Fixes to * receive() logic state machine. * * Revision 3.4.1.4 89/03/29 12:29:10 louie * The variable 'mode' in the peer structure was renamed 'hmode'. Add * poll_update() calls in a few places per Mills. The receive() procedure is * now table driven. The poll_update procedure only randomized the timer * when the interval changes. If we lose synchronization, don't zap sys.stratum. * Clean up the sanity_check() routine a bit. * * Revision 3.4.1.3 89/03/22 18:32:31 louie * patch3: Use new RCS headers. * * Revision 3.4.1.2 89/03/22 18:02:22 louie * Add some fiddles for BROADCAST NTP mode. In the receive procedure, set the * reachability shift register of peers that are configured, even if we won't * synchronized to them. Fix adjustment of delay in the process_packet() * routine. Repair byteswapping problem. * * * Revision 3.4.1.1 89/03/20 00:10:06 louie * patch1: sys.refid could have garbage left if the peer we're synchronized to * patch1: is lost. * * Revision 3.4 89/03/17 18:37:05 louie * Latest test release. * * Revision 3.3.1.1 89/03/17 18:26:02 louie * Oh my, peer->hpoll wasn't being set in peer_update! * * Revision 3.3 89/03/15 14:19:49 louie * New baseline for next release. * * Revision 3.2.1.2 89/03/15 13:54:41 louie * Change use of "%lf" in format strings to use "%f" instead. * poll_update no longer returns a value, due to a change in the transmit * procedure; it is now declared as returning void. Removed syslog * message "Dropping peer ...". You still get messages for peers which * were configured when reachability is lost with them. Clarification of * calling poll_update on sys.peer rather than on the host whose packet * we're processing when sys.peer changes. poll_update has been updated * including randomizing peer.timer. * * Revision 3.2.1.1 89/03/10 11:30:33 louie * Remove computation of peer->timer that was present due to a bug in the NTP * spec. Don't set sys.precision in the NTP protocol initialization; this has * bad side effects with the code that get tick from the kernel and the NTP * config file scanner. * * Revision 3.2 89/03/07 18:24:54 louie * New version of UNIX NTP daemon based on the 6 March 1989 draft of the new * NTP protocol specification. This version has a bunch of bugs fixes and * new algorithms which were discussed on the NTP mailing list over the past * few weeks. * * Revision 3.1.1.1 89/02/15 08:57:34 louie * *** empty log message *** * * * Revision 3.1 89/01/30 14:43:10 louie * Second UNIX NTP test release. * * Revision 3.0 88/12/12 15:59:35 louie * Test release of new UNIX NTP software. This version should conform to the * revised NTP protocol specification. * */#include <stdio.h>#include <sys/types.h>#include <sys/param.h>#include <sys/uio.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/ioctl.h>#include <sys/resource.h>#include <net/if.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/udp.h>#include <arpa/inet.h>#include <netdb.h>#include <strings.h>#include <errno.h>#include <syslog.h>#include "ntp.h"int peer_switches, peer_sw_inhibited;struct ntp_peer dummy_peer;extern double WayTooBig;extern unsigned long clock_watchdog;#ifdef DEBUGextern int debug;extern void dump_pkt();#endifextern int trusting, logstats;extern struct sysdata sys;extern struct list peer_list;extern struct ntp_peer *check_peer();extern struct servent *servp;extern char *malloc(), *ntoa();extern double drift_comp, compliance; /* logical clock variables */extern double s_fixed_to_double(), ul_fixed_to_double();extern void make_new_peer(), double_to_s_fixed(), tstamp(), demobilize(); #ifdef REFCLOCKvoid refclock_input();#endifvoid process_packet(), clock_update(), clear(), clock_filter(), receive(), select_clock(), poll_update();/* 3.4. Event Processing *//* 3.4.1. Transmit Procedure */voidtransmit(peer) struct ntp_peer *peer;{ struct timeval txtv; static struct ntpdata ntpframe; struct ntpdata *pkt = &ntpframe; int i; pkt->status = sys.leap | NTPVERSION_1 | peer->hmode; pkt->stratum = sys.stratum; pkt->ppoll = peer->hpoll; pkt->precision = (char) sys.precision; pkt->distance = sys.distance; pkt->dispersion = sys.dispersion; pkt->refid = sys.refid; pkt->reftime = sys.reftime; pkt->org = peer->org; pkt->rec = peer->rec; (void) gettimeofday(&txtv, (struct timezone *) 0);#if 0 if (peer->flags & PEER_FL_AUTHENABLE) { /* add encryption time into the timestamp */ tstamp(&pkt->xmt, &txtv); /* call encrypt() procedure */ pkt->keyid = ???; pkt->mac = ???; } else { pkt->mac[0] = pkt->mac[1] = 0; pkt->keyid = 0; /* XXX */ tstamp(&pkt->xmt, &txtv); }#else tstamp(&pkt->xmt, &txtv);#endif peer->xmt = pkt->xmt; if ((peer->flags & (PEER_FL_BCAST|PEER_FL_REFCLOCK)) == 0) { /* select correct socket to send reply on */ if (sendto(addrs[(peer->sock < 0 ? 0 : peer->sock)].fd, (char *) pkt, sizeof(ntpframe), 0, &peer->src, sizeof(peer->src)) < 0) { syslog(LOG_ERR, "sendto: %s %m", ntoa(peer->src.sin_addr)); return; }#ifdef REFCLOCK } else if (peer->flags & PEER_FL_REFCLOCK) { /* Special version of code below, adjusted for refclocks */ peer->pkt_sent++; i = peer->reach; /* save a copy */ peer->reach = (peer->reach << 1) & NTP_WINDOW_SHIFT_MASK; if (i && peer->reach == 0) { syslog(LOG_INFO, "Lost reachability with %.4s", (char *)&peer->refid);#ifdef DEBUG if (debug) printf("Lost reachability with %.4s\n", (char *)&peer->refid);#endif } if (peer->reach == 0) clear(peer); if (peer->valid < 2) peer->valid++; else { clock_filter(peer, 0.0, 0.0); /* call with invalid values */ select_clock(); /* and try to reselect clock */ } peer->timer = 1<<NTP_MINPOLL; /* poll refclocks frequently */ refclock_input(peer, pkt); return;#endif REFCLOCK } else {#ifdef BROADCAST_NTP if (sendto(addrs[peer->sock].fd, (char *) pkt, sizeof(ntpframe), 0, &peer->src, sizeof(peer->src)) < 0) { syslog(LOG_ERR, "bcast sendto: %s %m", ntoa(peer->src.sin_addr)); return; }#else return;#endif }#ifdef DEBUG if (debug > 5) { printf("\nSent "); dump_pkt(&peer->src, pkt, (struct ntp_peer *)NULL); }#endif peer->pkt_sent++; i = peer->reach; /* save a copy */ peer->reach = (peer->reach << 1) & NTP_WINDOW_SHIFT_MASK; if ((peer->reach == 0) && ((peer->flags & PEER_FL_CONFIG) == 0) && (peer != &dummy_peer)) { demobilize(&peer_list, peer); return; } if (i && peer->reach == 0) { syslog(LOG_INFO, "Lost reachability with %s", ntoa(peer->src.sin_addr));#ifdef DEBUG if (debug) printf("Lost reachability with %s", ntoa(peer->src.sin_addr));#endif } if (peer->reach == 0) { clear(peer); peer->sock = -1; /* since he fell off the end of the earth, don't depend on local address any longer */ } if (peer->valid < 2) peer->valid++; else { clock_filter(peer, 0.0, 0.0); /* call with invalid values */ select_clock(); /* and try to reselect clock */ if (sys.peer != NULL) poll_update(sys.peer, NTP_MINPOLL); } peer->timer = 1<<(MAX(MIN(peer->ppoll, MIN(peer->hpoll, NTP_MAXPOLL)), NTP_MINPOLL)); if (peer->estdisp > PEER_THRESHOLD) poll_update(peer, peer->hpoll - 1); else poll_update(peer, peer->hpoll + 1);}#ifdef REFCLOCKvoidrefclock_input(peer, pkt) struct ntpdata *pkt; struct ntp_peer *peer;{ struct timeval *tvp; struct timeval *otvp; if (read_clock(peer->sock, &tvp, &otvp)) return; tstamp(&pkt->rec, tvp); pkt->xmt = pkt->rec; pkt->reftime = pkt->rec; tstamp(&pkt->org, otvp); peer->xmt = pkt->org; pkt->refid = peer->refid; pkt->status &= ~ALARM; pkt->stratum = peer->stratum; pkt->ppoll = 0xff; pkt->precision = peer->precision; double_to_s_fixed(&pkt->distance, 0.0); double_to_s_fixed(&pkt->dispersion, 0.0);#ifdef DEBUG if (debug > 5) { printf("\nFaking packet "); dump_pkt(&peer->src, pkt, (struct ntp_peer *)NULL); }#endif receive((struct sockaddr_in *)peer, pkt, otvp, -1); return;}#endif REFCLOCK/* 3.4.2. Receive Procedure */voidreceive(dst, pkt, tvp, sock) struct sockaddr_in *dst; struct ntpdata *pkt; struct timeval *tvp; int sock;{ struct ntp_peer *peer; int peer_mode;#define ACT_ERROR 1#define ACT_RECV 2#define ACT_XMIT 3#define ACT_PKT 4 static char actions[5][5] = { /* Sym Act Sym Pas Client Server Broadcast |Host / */ /* -------- -------- -------- --------- --------- | / Peer */ /* ------------ */ {ACT_PKT, ACT_PKT, ACT_RECV, ACT_XMIT, ACT_XMIT}, /* Sym Act */ {ACT_PKT, ACT_ERROR, ACT_RECV, ACT_ERROR, ACT_ERROR}, /* Sym Pas */ {ACT_XMIT, ACT_XMIT, ACT_ERROR, ACT_XMIT, ACT_XMIT}, /* Client */ {ACT_PKT, ACT_ERROR, ACT_RECV, ACT_ERROR, ACT_ERROR}, /* Server */ {ACT_PKT, ACT_ERROR, ACT_RECV, ACT_ERROR, ACT_ERROR}};/* Broadcast */ /* if we're only going to support NTP Version 2 then this stuff isn't necessary, right? */ if ((peer_mode = pkt->status & MODEMASK) == 0 && dst) { /* packet from an older NTP implementation. Synthesize the correct mode. The mapping goes like this: pkt source port pkt dst port Mode --------------- ------------ ---- NTP Port NTP Port symmetric active NTP Port not NTP Port server not NTP Port NTP Port client not NTP Port not NTP Port <not possible> Now, since we only are processing packets with the destination being NTP Port, it reduces to the two cases: pkt source port pkt dst port Mode --------------- ------------ ---- NTP Port NTP Port symmetric active not NTP Port NTP Port client */ if (dst->sin_port == servp->s_port) peer_mode = MODE_SYM_ACT; else peer_mode = MODE_CLIENT;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?