FreeBSD/contrib/ntp/ntpdate/ntpdate.c
/*
 * receive - receive and process an incoming frame
 */
receive and process an incoming frame
receive and process an incoming frame
static void
receive(
	struct recvbuf *rbufp
	)
{
	register struct pkt *rpkt;
	register struct server *server;
	register s_fp di;
	l_fp t10, t23, tmp;
	l_fp org;
	l_fp rec;
	l_fp ci;
	int has_mac;
	int is_authentic;
	if (debug)
		printf("receive(%s)\n", stoa(&rbufp->recv_srcadr));
	if (rbufp->recv_length == LEN_PKT_NOMAC)
		has_mac = 0;
	else if (rbufp->recv_length >= (int)LEN_PKT_NOMAC)
		has_mac = 1;
	else {
		if (debug)
			printf("receive: packet length %d\n",
			   rbufp->recv_length);
		return; 		
	}
	rpkt = &(rbufp->recv_pkt);
	if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION ||
		PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) {
		return;
	}
	if ((PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER
		 && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE)
		|| rpkt->stratum >= STRATUM_UNSPEC) {
		if (debug)
			printf("receive: mode %d stratum %d\n",
			   PKT_MODE(rpkt->li_vn_mode), rpkt->stratum);
		return;
	}
	server = findserver(&(rbufp->recv_srcadr));
	if (server == NULL) {
		if (debug)
			printf("receive: server not found\n");
		return;
	}
	NTOHL_FP(&rpkt->org, &org);
	if (!L_ISEQU(&org, &server->xmt)) {
		if (debug)
			printf("receive: pkt.org and peer.xmt differ\n");
		return;
	}
	if (!sys_authenticate)
		is_authentic = 1;
	else {
		is_authentic = 0;
		if (debug > 3)
			printf("receive: rpkt keyid=%ld sys_authkey=%ld decrypt=%ld\n",
			   (long int)ntohl(rpkt->exten[0]), (long int)sys_authkey,
			   (long int)authdecrypt(sys_authkey, (u_int32 *)rpkt,
				LEN_PKT_NOMAC, (size_t)(rbufp->recv_length - LEN_PKT_NOMAC)));
		if (has_mac && ntohl(rpkt->exten[0]) == sys_authkey &&
			authdecrypt(sys_authkey, (u_int32 *)rpkt, LEN_PKT_NOMAC,
			(size_t)(rbufp->recv_length - LEN_PKT_NOMAC)))
			is_authentic = 1;
		if (debug)
			printf("receive: authentication %s\n",
			   is_authentic ? "passed" : "failed");
	}
	server->trust <<= 1;
	if (!is_authentic)
		server->trust |= 1;
	if (LEAP_NOTINSYNC == PKT_LEAP(rpkt->li_vn_mode) &&
	    STRATUM_PKT_UNSPEC == rpkt->stratum &&
	    !memcmp("RATE", &rpkt->refid, 4)) {
		msyslog(LOG_ERR, "%s rate limit response from server.",
			stoa(&rbufp->recv_srcadr));
		server->event_time = 0;
		complete_servers++;
		return;
	}
	server->leap = PKT_LEAP(rpkt->li_vn_mode);
	server->stratum = PKT_TO_STRATUM(rpkt->stratum);
	server->precision = rpkt->precision;
	server->rootdelay = ntohl(rpkt->rootdelay);
	server->rootdisp = ntohl(rpkt->rootdisp);
	server->refid = rpkt->refid;
	NTOHL_FP(&rpkt->reftime, &server->reftime);
	NTOHL_FP(&rpkt->rec, &rec);
	NTOHL_FP(&rpkt->xmt, &server->org);
	if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) {
		server->event_time = current_time + sys_timeout;
		return;
	}
	t10 = server->org;		
	L_SUB(&t10, &rbufp->recv_time); 
	t23 = rec;			
	L_SUB(&t23, &org);		
	ci = t10;
	L_RSHIFT(&ci);
	tmp = t23;
	L_RSHIFT(&tmp);
	L_ADD(&ci, &tmp);
	L_SUB(&t23, &t10);
	di = LFPTOFP(&t23);
	if (debug > 3)
		printf("offset: %s, delay %s\n", lfptoa(&ci, 6), fptoa(di, 5));
	di += (FP_SECOND >> (-(int)NTPDATE_PRECISION))
		+ (FP_SECOND >> (-(int)server->precision)) + NTP_MAXSKW;
	if (di <= 0) {		
		L_CLR(&ci);
		di = 0;
	} else {
		di = max(di, NTP_MINDIST);
	}
	server_data(server, (s_fp) di, &ci, 0);
	if ((int)server->filter_nextpt >= sys_samples) {
		server->event_time = 0;
		complete_servers++;
		return;
	}
	server->event_time = current_time + sys_timeout;
}
static void receive ( struct recvbuf * rbufp ) { register struct pkt * rpkt ; register struct server * server ; register s_fp di ; l_fp t10 , t23 , tmp ; l_fp org ; l_fp rec ; l_fp ci ; int has_mac ; int is_authentic ; if ( debug ) printf ( " \n " , stoa ( & rbufp -> recv_srcadr ) ) ; if ( rbufp -> recv_length == LEN_PKT_NOMAC ) has_mac = 0 ; else if ( rbufp -> recv_length >= ( int ) LEN_PKT_NOMAC ) has_mac = 1 ; else { if ( debug ) printf ( " \n " , rbufp -> recv_length ) ; return ; } rpkt = & ( rbufp -> recv_pkt ) ; if ( PKT_VERSION ( rpkt -> li_vn_mode ) < NTP_OLDVERSION || PKT_VERSION ( rpkt -> li_vn_mode ) > NTP_VERSION ) { return ; } if ( ( PKT_MODE ( rpkt -> li_vn_mode ) != MODE_SERVER && PKT_MODE ( rpkt -> li_vn_mode ) != MODE_PASSIVE ) || rpkt -> stratum >= STRATUM_UNSPEC ) { if ( debug ) printf ( " \n " , PKT_MODE ( rpkt -> li_vn_mode ) , rpkt -> stratum ) ; return ; } server = findserver ( & ( rbufp -> recv_srcadr ) ) ; if ( server == NULL ) { if ( debug ) printf ( " \n " ) ; return ; } NTOHL_FP ( & rpkt -> org , & org ) ; if ( ! L_ISEQU ( & org , & server -> xmt ) ) { if ( debug ) printf ( " \n " ) ; return ; } if ( ! sys_authenticate ) is_authentic = 1 ; else { is_authentic = 0 ; if ( debug > 3 ) printf ( " \n " , ( long int ) ntohl ( rpkt -> exten [ 0 ] ) , ( long int ) sys_authkey , ( long int ) authdecrypt ( sys_authkey , ( u_int32 * ) rpkt , LEN_PKT_NOMAC , ( size_t ) ( rbufp -> recv_length - LEN_PKT_NOMAC ) ) ) ; if ( has_mac && ntohl ( rpkt -> exten [ 0 ] ) == sys_authkey && authdecrypt ( sys_authkey , ( u_int32 * ) rpkt , LEN_PKT_NOMAC , ( size_t ) ( rbufp -> recv_length - LEN_PKT_NOMAC ) ) ) is_authentic = 1 ; if ( debug ) printf ( " \n " , is_authentic ? " " : " " ) ; } server -> trust <<= 1 ; if ( ! is_authentic ) server -> trust |= 1 ; if ( LEAP_NOTINSYNC == PKT_LEAP ( rpkt -> li_vn_mode ) && STRATUM_PKT_UNSPEC == rpkt -> stratum && ! memcmp ( " " , & rpkt -> refid , 4 ) ) { msyslog ( LOG_ERR , " " , stoa ( & rbufp -> recv_srcadr ) ) ; server -> event_time = 0 ; complete_servers ++ ; return ; } server -> leap = PKT_LEAP ( rpkt -> li_vn_mode ) ; server -> stratum = PKT_TO_STRATUM ( rpkt -> stratum ) ; server -> precision = rpkt -> precision ; server -> rootdelay = ntohl ( rpkt -> rootdelay ) ; server -> rootdisp = ntohl ( rpkt -> rootdisp ) ; server -> refid = rpkt -> refid ; NTOHL_FP ( & rpkt -> reftime , & server -> reftime ) ; NTOHL_FP ( & rpkt -> rec , & rec ) ; NTOHL_FP ( & rpkt -> xmt , & server -> org ) ; if ( L_ISZERO ( & rec ) || ! L_ISHIS ( & server -> org , & rec ) ) { server -> event_time = current_time + sys_timeout ; return ; } t10 = server -> org ; L_SUB ( & t10 , & rbufp -> recv_time ) ; t23 = rec ; L_SUB ( & t23 , & org ) ; ci = t10 ; L_RSHIFT ( & ci ) ; tmp = t23 ; L_RSHIFT ( & tmp ) ; L_ADD ( & ci , & tmp ) ; L_SUB ( & t23 , & t10 ) ; di = LFPTOFP ( & t23 ) ; if ( debug > 3 ) printf ( " \n " , lfptoa ( & ci , 6 ) , fptoa ( di , 5 ) ) ; di += ( FP_SECOND >> ( - ( int ) NTPDATE_PRECISION ) ) + ( FP_SECOND >> ( - ( int ) server -> precision ) ) + NTP_MAXSKW ; if ( di <= 0 ) { L_CLR ( & ci ) ; di = 0 ; } else { di = max ( di , NTP_MINDIST ) ; } server_data ( server , ( s_fp ) di , & ci , 0 ) ; if ( ( int ) server -> filter_nextpt >= sys_samples ) { server -> event_time = 0 ; complete_servers ++ ; return ; } server -> event_time = current_time + sys_timeout ; }
receive - receive and process an incoming frame
receive - receive and process an incoming frame
/*
	 * Check to see if the packet basically looks like something
	 * intended for us.
	 */ /* funny length packet */ /*
	 * So far, so good.  See if this is from a server we know.
	 */ /*
	 * Decode the org timestamp and make sure we're getting a response
	 * to our last request.
	 */ /*
	 * Check out the authenticity if we're doing that.
	 */ /*
	 * Check for a KoD (rate limiting) response, cease and decist.
	 */ /*
	 * Looks good.	Record info from the packet.
	 */ /*
	 * Make sure the server is at least somewhat sane.	If not, try
	 * again.
	 */ /*
	 * Calculate the round trip delay (di) and the clock offset (ci).
	 * We use the equations (reordered from those in the spec):
	 *
	 * d = (t2 - t3) - (t1 - t0)
	 * c = ((t2 - t3) + (t1 - t0)) / 2
	 */ /* pkt.xmt == t1 */ /* recv_time == t0*/ /* pkt.rec == t2 */ /* pkt->org == t3 */ /* now have (t2 - t3) and (t0 - t1).	Calculate (ci) and (di) */ /*
	 * Calculate (ci) = ((t1 - t0) / 2) + ((t2 - t3) / 2)
	 * For large offsets this may prevent an overflow on '+'
	 */ /*
	 * Calculate di in t23 in full precision, then truncate
	 * to an s_fp.
	 */ /* value still too raunchy to use? */ /*
	 * Shift this data in, then schedule another transmit.
	 */ /*
		 * Got all the data we need.  Mark this guy
		 * completed and return.
		 */