コード例 #1
0
ファイル: utilities.c プロジェクト: execunix/vinos
/* Output a long floating point value in hex in the style described above 
 */
void
l_fp_output(
	l_fp *	ts,
	FILE *	output
	)
{
	fprintf(output, "%s\n", prettydate(ts));
}
コード例 #2
0
ファイル: refclock_wwvb.c プロジェクト: enukane/netbsd-src
/*
 * wwvb_timer - called once per second by the transmit procedure
 */
static void
wwvb_timer(
	int unit,
	struct peer *peer
	)
{
	register struct wwvbunit *up;
	struct refclockproc *pp;
	char	pollchar;	/* character sent to clock */
#ifdef DEBUG
	l_fp	now;
#endif

	/*
	 * Time to poll the clock. The Spectracom clock responds to a
	 * 'T' by returning a timecode in the format(s) specified above.
	 * Note there is no checking on state, since this may not be the
	 * only customer reading the clock. Only one customer need poll
	 * the clock; all others just listen in.
	 */
	pp = peer->procptr;
	up = pp->unitptr;
	if (up->linect > 0)
		pollchar = 'R';
	else
		pollchar = 'T';
	if (write(pp->io.fd, &pollchar, 1) != 1)
		refclock_report(peer, CEVNT_FAULT);
#ifdef DEBUG
	get_systime(&now);
	if (debug)
		printf("%c poll at %s\n", pollchar, prettydate(&now));
#endif
#ifdef HAVE_PPSAPI
	if (up->ppsapi_lit &&
	    refclock_pps(peer, &up->atom, pp->sloppyclockflag) > 0) {
		up->pcount++,
		peer->flags |= FLAG_PPS;
		peer->precision = PPS_PRECISION;
	}
#endif /* HAVE_PPSAPI */
}
コード例 #3
0
/*
 * wwvb_receive - receive data from the serial interface
 */
static void
wwvb_receive(
	struct recvbuf *rbufp
	)
{
	struct wwvbunit *up;
	struct refclockproc *pp;
	struct peer *peer;

	l_fp	trtmp;		/* arrival timestamp */
	int	tz;		/* time zone */
	int	day, month;	/* ddd conversion */
	int	temp;		/* int temp */
	char	syncchar;	/* synchronization indicator */
	char	qualchar;	/* quality indicator */
	char	leapchar;	/* leap indicator */
	char	dstchar;	/* daylight/standard indicator */
	char	tmpchar;	/* trashbin */

	/*
	 * Initialize pointers and read the timecode and timestamp
	 */
	peer = rbufp->recv_peer;
	pp = peer->procptr;
	up = pp->unitptr;
	temp = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);

	/*
	 * Note we get a buffer and timestamp for both a <cr> and <lf>,
	 * but only the <cr> timestamp is retained. Note: in format 0 on
	 * a Netclock/2 or upgraded 8170 the start bit is delayed 100
	 * +-50 us relative to the pps; however, on an unmodified 8170
	 * the start bit can be delayed up to 10 ms. In format 2 the
	 * reading precision is only to the millisecond. Thus, unless
	 * you have a PPS gadget and don't have to have the year, format
	 * 0 provides the lowest jitter.
	 * Save the timestamp of each <CR> in up->laststamp.  Lines with
	 * no characters occur for every <LF>, and for some <CR>s when
	 * format 0 is used. Format 0 starts and ends each cycle with a
	 * <CR><LF> pair, format 2 starts each cycle with its only pair.
	 * The preceding <CR> is the on-time character for both formats.
	 * The timestamp provided with non-empty lines corresponds to
	 * the <CR> following the timecode, which is ultimately not used
	 * with format 0 and is used for the following timecode for
	 * format 2.
	 */
	if (temp == 0) {
		if (up->prev_eol_cr) {
			DPRINTF(2, ("wwvb: <LF> @ %s\n",
				    prettydate(&trtmp)));
		} else {
			up->laststamp = trtmp;
			DPRINTF(2, ("wwvb: <CR> @ %s\n", 
				    prettydate(&trtmp)));
		}
		up->prev_eol_cr = !up->prev_eol_cr;
		return;
	}
	pp->lencode = temp;
	pp->lastrec = up->laststamp;
	up->laststamp = trtmp;
	up->prev_eol_cr = TRUE;
	DPRINTF(2, ("wwvb: code @ %s\n"
		    "       using %s minus one char\n",
		    prettydate(&trtmp), prettydate(&pp->lastrec)));
	if (L_ISZERO(&pp->lastrec))
		return;

	/*
	 * We get down to business, check the timecode format and decode
	 * its contents. This code uses the timecode length to determine
	 * format 0, 2 or 3. If the timecode has invalid length or is
	 * not in proper format, we declare bad format and exit.
	 */
	syncchar = qualchar = leapchar = dstchar = ' ';
	tz = 0;
	switch (pp->lencode) {

	case LENWWVB0:

		/*
		 * Timecode format 0: "I  ddd hh:mm:ss DTZ=nn"
		 */
		if (sscanf(pp->a_lastcode,
		    "%c %3d %2d:%2d:%2d%c%cTZ=%2d",
		    &syncchar, &pp->day, &pp->hour, &pp->minute,
		    &pp->second, &tmpchar, &dstchar, &tz) == 8) {
			pp->nsec = 0;
			break;
		}
		goto bad_format;

	case LENWWVB2:

		/*
		 * Timecode format 2: "IQyy ddd hh:mm:ss.mmm LD" */
		if (sscanf(pp->a_lastcode,
		    "%c%c %2d %3d %2d:%2d:%2d.%3ld %c",
		    &syncchar, &qualchar, &pp->year, &pp->day,
		    &pp->hour, &pp->minute, &pp->second, &pp->nsec,
		    &leapchar) == 9) {
			pp->nsec *= 1000000;
			break;
		}
		goto bad_format;

	case LENWWVB3:

		/*
		 * Timecode format 3: "0003I yyyymmdd hhmmss+0000SL#"
		 * WARNING: Undocumented, and the on-time character # is
		 * not yet handled correctly by this driver.  It may be
		 * as simple as compensating for an additional 1/960 s.
		 */
		if (sscanf(pp->a_lastcode,
		    "0003%c %4d%2d%2d %2d%2d%2d+0000%c%c",
		    &syncchar, &pp->year, &month, &day, &pp->hour,
		    &pp->minute, &pp->second, &dstchar, &leapchar) == 8)
		    {
			pp->day = ymd2yd(pp->year, month, day);
			pp->nsec = 0;
			break;
		}
		goto bad_format;

	default:
	bad_format:

		/*
		 * Unknown format: If dumping internal table, record
		 * stats; otherwise, declare bad format.
		 */
		if (up->linect > 0) {
			up->linect--;
			record_clock_stats(&peer->srcadr,
			    pp->a_lastcode);
		} else {
			refclock_report(peer, CEVNT_BADREPLY);
		}
		return;
	}

	/*
	 * Decode synchronization, quality and leap characters. If
	 * unsynchronized, set the leap bits accordingly and exit.
	 * Otherwise, set the leap bits according to the leap character.
	 * Once synchronized, the dispersion depends only on the
	 * quality character.
	 */
	switch (qualchar) {

	    case ' ':
		pp->disp = .001;
		pp->lastref = pp->lastrec;
		break;

	    case 'A':
		pp->disp = .01;
		break;

	    case 'B':
		pp->disp = .1;
		break;

	    case 'C':
		pp->disp = .5;
		break;

	    case 'D':
		pp->disp = MAXDISPERSE;
		break;

	    default:
		pp->disp = MAXDISPERSE;
		refclock_report(peer, CEVNT_BADREPLY);
		break;
	}
	if (syncchar != ' ')
		pp->leap = LEAP_NOTINSYNC;
	else if (leapchar == 'L')
		pp->leap = LEAP_ADDSECOND;
	else
		pp->leap = LEAP_NOWARNING;

	/*
	 * Process the new sample in the median filter and determine the
	 * timecode timestamp, but only if the PPS is not in control.
	 */
#ifdef HAVE_PPSAPI
	up->tcount++;
	if (peer->flags & FLAG_PPS)
		return;

#endif /* HAVE_PPSAPI */
	if (!refclock_process_f(pp, pp->fudgetime2))
		refclock_report(peer, CEVNT_BADTIME);
}
コード例 #4
0
/*
** Check if it's data for us and whether it's useable or not.
**
** If not, return a failure code so we can delete this server from our list
** and continue with another one.
*/
int
process_pkt (
	struct pkt *rpkt,
	sockaddr_u *sender,
	int pkt_len,
	int mode,
	struct pkt *spkt,
	const char * func_name
	)
{
	u_int		key_id;
	struct key *	pkt_key;
	int		is_authentic;
	int		mac_size;
	u_int		exten_len;
	u_int32 *       exten_end;
	u_int32 *       packet_end;
	l_fp		sent_xmt;
	l_fp		resp_org;

	// key_id = 0;
	pkt_key = NULL;
	is_authentic = (HAVE_OPT(AUTHENTICATION)) ? 0 : -1;

	/*
	 * 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 6,
	 * the packet is authenticated with SHA. If 2 or 4, the packet
	 * is a runt and discarded forthwith. If greater than 6, an
	 * extension field is present, so we subtract the length of the
	 * field and go around again.
	 */
	if (pkt_len < (int)LEN_PKT_NOMAC || (pkt_len & 3) != 0) {
		msyslog(LOG_ERR,
			"%s: Incredible packet length: %d.  Discarding.",
			func_name, pkt_len);
		return PACKET_UNUSEABLE;
	}

	/* HMS: the following needs a bit of work */
	/* Note: pkt_len must be a multiple of 4 at this point! */
	packet_end = (void*)((char*)rpkt + pkt_len);
	exten_end = skip_efields(rpkt->exten, packet_end);
	if (NULL == exten_end) {
		msyslog(LOG_ERR,
			"%s: Missing extension field.  Discarding.",
			func_name);
		return PACKET_UNUSEABLE;
	}

	/* get size of MAC in cells; can be zero */
	exten_len = (u_int)(packet_end - exten_end);

	/* deduce action required from remaining length */
	switch (exten_len) {

	case 0:	/* no Legacy MAC */
		break;

	case 1:	/* crypto NAK */		
		/* Only if the keyID is 0 and there were no EFs */
		key_id = ntohl(*exten_end);
		printf("Crypto NAK = 0x%08x from %s\n", key_id, stoa(sender));
		break;

	case 3: /* key ID + 3DES MAC -- unsupported! */
		msyslog(LOG_ERR,
			"%s: Key ID + 3DES MAC is unsupported.  Discarding.",
			func_name);
		return PACKET_UNUSEABLE;

	case 5:	/* key ID + MD5 MAC */
	case 6:	/* key ID + SHA MAC */
		/*
		** Look for the key used by the server in the specified
		** keyfile and if existent, fetch it or else leave the
		** pointer untouched
		*/
		key_id = ntohl(*exten_end);
		get_key(key_id, &pkt_key);
		if (!pkt_key) {
			printf("unrecognized key ID = 0x%08x\n", key_id);
			break;
		}
		/*
		** Seems like we've got a key with matching keyid.
		**
		** Generate a md5sum of the packet with the key from our
		** keyfile and compare those md5sums.
		*/
		mac_size = exten_len << 2;
		if (!auth_md5(rpkt, pkt_len - mac_size,
			      mac_size - 4, pkt_key)) {
			is_authentic = FALSE;
			break;
		}
		/* Yay! Things worked out! */
		is_authentic = TRUE;
		TRACE(1, ("sntp %s: packet from %s authenticated using key id %d.\n",
			  func_name, stoa(sender), key_id));
		break;

	default:
		msyslog(LOG_ERR,
			"%s: Unexpected extension length: %d.  Discarding.",
			func_name, exten_len);
		return PACKET_UNUSEABLE;
	}

	switch (is_authentic) {

	case -1:	/* unknown */
		break;

	case 0:		/* not authentic */
		return SERVER_AUTH_FAIL;
		break;

	case 1:		/* authentic */
		break;

	default:	/* error */
		break;
	}

	/* Check for server's ntp version */
	if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION ||
		PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) {
		msyslog(LOG_ERR,
			"%s: Packet shows wrong version (%d)",
			func_name, PKT_VERSION(rpkt->li_vn_mode));
		return SERVER_UNUSEABLE;
	} 
	/* We want a server to sync with */
	if (PKT_MODE(rpkt->li_vn_mode) != mode &&
	    PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE) {
		msyslog(LOG_ERR,
			"%s: mode %d stratum %d", func_name, 
			PKT_MODE(rpkt->li_vn_mode), rpkt->stratum);
		return SERVER_UNUSEABLE;
	}
	/* Stratum is unspecified (0) check what's going on */
	if (STRATUM_PKT_UNSPEC == rpkt->stratum) {
		char *ref_char;

		TRACE(1, ("%s: Stratum unspecified, going to check for KOD (stratum: %d)\n", 
			  func_name, rpkt->stratum));
		ref_char = (char *) &rpkt->refid;
		TRACE(1, ("%s: Packet refid: %c%c%c%c\n", func_name,
			  ref_char[0], ref_char[1], ref_char[2], ref_char[3]));
		/* If it's a KOD packet we'll just use the KOD information */
		if (ref_char[0] != 'X') {
			if (strncmp(ref_char, "DENY", 4) == 0)
				return KOD_DEMOBILIZE;
			if (strncmp(ref_char, "RSTR", 4) == 0)
				return KOD_DEMOBILIZE;
			if (strncmp(ref_char, "RATE", 4) == 0)
				return KOD_RATE;
			/*
			** There are other interesting kiss codes which
			** might be interesting for authentication.
			*/
		}
	}
	/* If the server is not synced it's not really useable for us */
	if (LEAP_NOTINSYNC == PKT_LEAP(rpkt->li_vn_mode)) {
		msyslog(LOG_ERR,
			"%s: %s not in sync, skipping this server",
			func_name, stoa(sender));
		return SERVER_UNUSEABLE;
	}

	/*
	 * Decode the org timestamp and make sure we're getting a response
	 * to our last request, but only if we're not in broadcast mode.
	 */
	if (MODE_BROADCAST == mode)
		return pkt_len;

	if (!L_ISEQU(&rpkt->org, &spkt->xmt)) {
		NTOHL_FP(&rpkt->org, &resp_org);
		NTOHL_FP(&spkt->xmt, &sent_xmt);
		msyslog(LOG_ERR,
			"%s response org expected to match sent xmt",
			stoa(sender));
		msyslog(LOG_ERR, "resp org: %s", prettydate(&resp_org));
		msyslog(LOG_ERR, "sent xmt: %s", prettydate(&sent_xmt));
		return PACKET_UNUSEABLE;
	}

	return pkt_len;
}