📄 ntp_proto.c
字号:
/* * ntp_proto.c - NTP version 4 protocol machinery * * ATTENTION: Get approval from Dave Mills on all changes to this file! * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include "ntpd.h"#include "ntp_stdlib.h"#include "ntp_unixtime.h"#include "ntp_control.h"#include "ntp_string.h"#include <stdio.h>#if defined(VMS) && defined(VMS_LOCALUNIT) /*wjm*/#include "ntp_refclock.h"#endif#if defined(__FreeBSD__) && __FreeBSD__ >= 3#include <sys/sysctl.h>#endif/* * This macro defines the authentication state. If x is 1 authentication * is required; othewise it is optional. */#define AUTH(x, y) ((x) ? (y) == AUTH_OK : (y) == AUTH_OK || \ (y) == AUTH_NONE)/* * System variables are declared here. See Section 3.2 of the * specification. */u_char sys_leap; /* system leap indicator */u_char sys_stratum; /* stratum of system */s_char sys_precision; /* local clock precision (log2 s) */double sys_rootdelay; /* roundtrip delay to primary source */double sys_rootdispersion; /* dispersion to primary source */u_int32 sys_refid; /* source/loop in network byte order */static double sys_offset; /* current local clock offset */l_fp sys_reftime; /* time we were last updated */struct peer *sys_peer; /* our current peer */struct peer *sys_pps; /* our PPS peer */struct peer *sys_prefer; /* our cherished peer */int sys_kod; /* kod credit */int sys_kod_rate = 2; /* max kod packets per second */#ifdef OPENSSLu_long sys_automax; /* maximum session key lifetime */#endif /* OPENSSL *//* * Nonspecified system state variables. */int sys_bclient; /* broadcast client enable */double sys_bdelay; /* broadcast client default delay */int sys_calldelay; /* modem callup delay (s) */int sys_authenticate; /* requre authentication for config */l_fp sys_authdelay; /* authentication delay */static u_long sys_authdly[2]; /* authentication delay shift reg */static double sys_mindisp = MINDISPERSE; /* min disp increment (s) */static double sys_maxdist = MAXDISTANCE; /* selection threshold (s) */double sys_jitter; /* system jitter (s) */static int sys_hopper; /* anticlockhop counter */static int sys_maxhop = MAXHOP; /* anticlockhop counter threshold */int leap_next; /* leap consensus */keyid_t sys_private; /* private value for session seed */int sys_manycastserver; /* respond to manycast client pkts */int peer_ntpdate; /* active peers in ntpdate mode */int sys_survivors; /* truest of the truechimers */#ifdef OPENSSLchar *sys_hostname; /* gethostname() name */#endif /* OPENSSL *//* * TOS and multicast mapping stuff */int sys_floor = 0; /* cluster stratum floor */int sys_ceiling = STRATUM_UNSPEC; /* cluster stratum ceiling */int sys_minsane = 1; /* minimum candidates */int sys_minclock = NTP_MINCLOCK; /* minimum survivors */int sys_maxclock = NTP_MAXCLOCK; /* maximum candidates */int sys_cohort = 0; /* cohort switch */int sys_orphan = STRATUM_UNSPEC + 1; /* orphan stratum */double sys_orphandelay = 0; /* orphan root delay */int sys_beacon = BEACON; /* manycast beacon interval */int sys_ttlmax; /* max ttl mapping vector index */u_char sys_ttl[MAX_TTL]; /* ttl mapping vector *//* * Statistics counters */u_long sys_stattime; /* time since reset */u_long sys_received; /* packets received */u_long sys_processed; /* packets processed */u_long sys_newversionpkt; /* current version */u_long sys_oldversionpkt; /* recent version */u_long sys_unknownversion; /* invalid version */u_long sys_restricted; /* access denied */u_long sys_badlength; /* bad length or format */u_long sys_badauth; /* bad authentication */u_long sys_limitrejected; /* rate exceeded */static double root_distance P((struct peer *));static void clock_combine P((struct peer **, int));static void peer_xmit P((struct peer *));static void fast_xmit P((struct recvbuf *, int, keyid_t, int));static void clock_update P((void));static int default_get_precision P((void));static int peer_unfit P((struct peer *));/* * transmit - Transmit Procedure. See Section 3.4.2 of the * specification. */voidtransmit( struct peer *peer /* peer structure pointer */ ){ int hpoll; /* * The polling state machine. There are two kinds of machines, * those that never expect a reply (broadcast and manycast * server modes) and those that do (all other modes). The dance * is intricate... */ /* * Orphan mode is active when enabled and when no servers less * than the orphan statum are available. In this mode packets * are sent at the orphan stratum. An orphan with no other * synchronization source is an orphan parent. It assumes root * delay zero and reference ID the loopback address. All others * are orphan children with root delay randomized over a 1-s * range. The root delay is used by the election algorithm to * select the order of synchronization. */ hpoll = peer->hpoll; if (sys_orphan < STRATUM_UNSPEC && sys_peer == NULL) { sys_leap = LEAP_NOWARNING; sys_stratum = sys_orphan; sys_refid = htonl(LOOPBACKADR); sys_rootdelay = 0; sys_rootdispersion = 0; } /* * In broadcast mode the poll interval is never changed from * minpoll. */ if (peer->cast_flags & (MDF_BCAST | MDF_MCAST)) { peer->outdate = current_time; peer_xmit(peer); poll_update(peer, hpoll); return; } /* * In manycast mode we start with unity ttl. The ttl is * increased by one for each poll until either sys_maxclock * servers have been found or the maximum ttl is reached. When * sys_maxclock servers are found we stop polling until one or * more servers have timed out or until less than minpoll * associations turn up. In this case additional better servers * are dragged in and preempt the existing ones. */ if (peer->cast_flags & MDF_ACAST) { peer->outdate = current_time; if (peer->unreach > sys_beacon) { peer->unreach = 0; peer->ttl = 0; peer_xmit(peer); } else if (sys_survivors < sys_minclock || peer_preempt < sys_maxclock) { if (peer->ttl < sys_ttlmax) peer->ttl++; peer_xmit(peer); } peer->unreach++; poll_update(peer, hpoll); return; } /* * In unicast modes the dance is much more intricate. It is * desigmed to back off whenever possible to minimize network * traffic. */ if (peer->burst == 0) { u_char oreach; /* * Update the reachability status. If not heard for * three consecutive polls, stuff infinity in the clock * filter. */ oreach = peer->reach; peer->outdate = current_time; if (peer == sys_peer) sys_hopper++; peer->reach <<= 1; if (!(peer->reach & 0x07)) clock_filter(peer, 0., 0., MAXDISPERSE); if (!peer->reach) { /* * Here the peer is unreachable. If it was * previously reachable, raise a trap. */ if (oreach) { report_event(EVNT_UNREACH, peer); peer->timereachable = current_time; } /* * Send a burst if enabled, but only once after * a peer becomes unreachable. If the prempt * flag is dim, bump the unreach counter by one; * otherwise, bump it by three. */ if (peer->flags & FLAG_IBURST && peer->unreach == 0) { peer->burst = NTP_BURST; } if (!(peer->flags & FLAG_PREEMPT)) peer->unreach++; else peer->unreach += 3; } else { /* * Here the peer is reachable. Set the poll * interval to the system poll interval. Send a * burst only if enabled and the peer is fit. * * Respond to the peer evaluation produced by * the selection algorithm. If less than the * outlyer level, up the unreach by three. If * there are excess associations, up the unreach * by two if not a candidate and by one if so. */ if (!(peer->flags & FLAG_PREEMPT)) { peer->unreach = 0; } else if (peer->status < CTL_PST_SEL_SELCAND) { peer->unreach += 3; } else if (peer_preempt > sys_maxclock) { if (peer->status < CTL_PST_SEL_SYNCCAND) peer->unreach += 2; else peer->unreach++; } else { peer->unreach = 0; } hpoll = sys_poll; if (peer->flags & FLAG_BURST && peer_unfit(peer)) peer->burst = NTP_BURST; } /* * Watch for timeout. If ephemeral or preemptable, toss * the rascal; otherwise, bump the poll interval. */ if (peer->unreach >= NTP_UNREACH) { if (peer->flags & FLAG_PREEMPT || !(peer->flags & FLAG_CONFIG)) { peer_clear(peer, "TIME"); unpeer(peer); return; } else { hpoll++; } } } else { peer->burst--; /* * If a broadcast client at this point, the burst has * concluded, so we switch to client mode and purge the * keylist, since no further transmissions will be made. */ if (peer->burst == 0) { if (peer->cast_flags & MDF_BCLNT) { peer->hmode = MODE_BCLIENT;#ifdef OPENSSL key_expire(peer);#endif /* OPENSSL */ } /* * If ntpdate mode and the clock has not been * set and all peers have completed the burst, * we declare a successful failure. */ if (mode_ntpdate) { peer_ntpdate--; if (peer_ntpdate == 0) { msyslog(LOG_NOTICE, "no reply; clock not set"); exit (0); } } } } /* * Do not transmit if in broadcast client mode. */ if (peer->hmode != MODE_BCLIENT) peer_xmit(peer); poll_update(peer, hpoll);}/* * receive - Receive Procedure. See section 3.4.3 in the specification. */voidreceive( struct recvbuf *rbufp ){ register struct peer *peer; /* peer structure pointer */ register struct pkt *pkt; /* receive packet pointer */ int hisversion; /* packet version */ int hisleap; /* packet leap indicator */ int hismode; /* packet mode */ int hisstratum; /* packet stratum */ int restrict_mask; /* restrict bits */ int has_mac; /* length of MAC field */ int authlen; /* offset of MAC field */ int is_authentic = 0; /* cryptosum ok */ keyid_t skeyid = 0; /* key ID */ struct sockaddr_storage *dstadr_sin; /* active runway */ struct peer *peer2; /* aux peer structure pointer */ l_fp p_org; /* origin timestamp */ l_fp p_rec; /* receive timestamp */ l_fp p_xmt; /* transmit timestamp */#ifdef OPENSSL keyid_t tkeyid = 0; /* temporary key ID */ keyid_t pkeyid = 0; /* previous key ID */ struct autokey *ap; /* autokey structure pointer */ int rval; /* cookie snatcher */#endif /* OPENSSL */ int retcode = AM_NOMATCH; /* * Monitor the packet and get restrictions. Note that the packet * length for control and private mode packets must be checked * by the service routines. Note that no statistics counters are * recorded for restrict violations, since these counters are in * the restriction routine. Note the careful distinctions here * between a packet with a format error and a packet that is * simply discarded without prejudice. Some restrictions have to * be handled later in order to generate a kiss-of-death packet. */ /* * Bogus port check is before anything, since it probably * reveals a clogging attack. */ sys_received++; if (SRCPORT(&rbufp->recv_srcadr) == 0) { sys_badlength++; return; /* bogus port */ } ntp_monitor(rbufp); restrict_mask = restrictions(&rbufp->recv_srcadr);#ifdef DEBUG if (debug > 1) printf("receive: at %ld %s<-%s flags %x restrict %03x\n", current_time, stoa(&rbufp->dstadr->sin), stoa(&rbufp->recv_srcadr), rbufp->dstadr->flags, restrict_mask);#endif if (restrict_mask & RES_IGNORE) { sys_restricted++; return; /* ignore everything */ } pkt = &rbufp->recv_pkt; hisversion = PKT_VERSION(pkt->li_vn_mode); hisleap = PKT_LEAP(pkt->li_vn_mode); hismode = (int)PKT_MODE(pkt->li_vn_mode); hisstratum = PKT_TO_STRATUM(pkt->stratum); if (hismode == MODE_PRIVATE) { if (restrict_mask & RES_NOQUERY) { sys_restricted++; return; /* no query private */ } process_private(rbufp, ((restrict_mask & RES_NOMODIFY) == 0)); return; } if (hismode == MODE_CONTROL) { if (restrict_mask & RES_NOQUERY) { sys_restricted++; return; /* no query control */ } process_control(rbufp, restrict_mask); return; } if (restrict_mask & RES_DONTSERVE) { sys_restricted++; return; /* no time */ } if (rbufp->recv_length < LEN_PKT_NOMAC) { sys_badlength++; return; /* runt packet */ } /* * Version check must be after the query packets, since they * intentionally use early version. */ if (hisversion == NTP_VERSION) { sys_newversionpkt++; /* new version */ } else if (!(restrict_mask & RES_VERSION) && hisversion >= NTP_OLDVERSION) { sys_oldversionpkt++; /* previous version */ } else { sys_unknownversion++; return; /* old version */ } /* * Figure out his mode and validate the packet. This has some * legacy raunch that probably should be removed. In very early * NTP versions mode 0 was equivalent to what later versions * would interpret as client mode. */ if (hismode == MODE_UNSPEC) { if (hisversion == NTP_OLDVERSION) { hismode = MODE_CLIENT; } else { sys_badlength++; return; /* invalid mode */ } } /* * Parse the extension field if present. We figure out whether * an extension field is present by measuring the MAC size. If * the number of words following the packet header is 0, no MAC * is present and the packet is not authenticated. If 1, the * packet is a crypto-NAK; if 3, the packet is authenticated * with DES; if 5, the packet is authenticated with MD5. If 2 or * 4, the packet is a runt and discarded forthwith. If greater
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -