Ejemplo n.º 1
0
/* [internal] Given a time stamp for a leap insertion (the exact begin
 * of the new leap era), create new leap frame and put it into the
 * table. This is the work horse for reading a leap file and getting a
 * leap second update via authenticated network packet.
 */
int/*BOOL*/
leapsec_raw(
	leap_table_t * pt,
	const vint64 * ttime,
	int            taiof,
	int            dynls)
{
	vint64		stime;
	struct calendar	fts;
	leap_info_t	li;

	/* Check that we only extend the table. Paranoia rulez! */
	if (pt->head.size && ucmpv64(ttime, &pt->info[0].ttime) <= 0) {
		errno = ERANGE;
		return FALSE;
	}

	ntpcal_ntp64_to_date(&fts, ttime);
	/* If this does not match the exact month start, bail out. */
	if (fts.monthday != 1 || fts.hour || fts.minute || fts.second) {
		errno = EINVAL;
		return FALSE;
	}
	fts.month--; /* was in range 1..12, no overflow here! */
	stime    = ntpcal_date_to_ntp64(&fts);
	li.ttime = *ttime;
	li.stime = ttime->D_s.lo - stime.D_s.lo;
	li.taiof = (int16_t)taiof;
	li.dynls = (dynls != 0);
	return add_range(pt, &li);
}
Ejemplo n.º 2
0
/* [internal] Given a time stamp for a leap insertion (the exact begin
 * of the new leap era), create new leap frame and put it into the
 * table. This is the work horse for reading a leap file and getting a
 * leap second update via authenticated network packet.
 */
bool
leapsec_raw(
	leap_table_t * pt,
	const time64_t   ttime,
	int            taiof,
	int            dynls)
{
	time64_t		starttime;
	struct calendar	fts;
	leap_info_t	li;

	/* Check that we only extend the table. Paranoia rulez! */
	if (pt->head.size && (ttime <= pt->info[0].ttime)) {
		errno = ERANGE;
		return false;
	}

	ntpcal_ntp64_to_date(&fts, ttime);
	/* If this does not match the exact month start, bail out. */
	if (fts.monthday != 1 || fts.hour || fts.minute || fts.second) {
		errno = EINVAL;
		return false;
	}
	fts.month--; /* was in range 1..12, no overflow here! */
	starttime    = ntpcal_date_to_ntp64(&fts);
	li.ttime = ttime;
	li.stime = time64lo(ttime) - time64lo(starttime);
	li.taiof = (int16_t)taiof;
	li.dynls = (dynls != 0);
	return add_range(pt, &li);
}
Ejemplo n.º 3
0
/* [internal] Take a time stamp and create a leap second frame for
 * it. This will schedule a leap second for the beginning of the next
 * month, midnight UTC. The 'insert' argument tells if a leap second is
 * added (!=0) or removed (==0). We do not handle multiple inserts
 * (yet?)
 *
 * Returns 1 if the insert worked, 0 otherwise. (It's not possible to
 * insert a leap second into the current history -- only appending
 * towards the future is allowed!)
 */
static int/*BOOL*/
leapsec_add(
	leap_table_t*  pt    ,
	const vint64 * now64 ,
	int            insert)
{
	vint64		ttime, stime;
	struct calendar	fts;
	leap_info_t	li;

	/* Check against the table expiration and the lates available
	 * leap entry. Do not permit inserts, only appends, and only if
	 * the extend the table beyond the expiration!
	 */
	if (   ucmpv64(now64, &pt->head.expire) < 0
	    || (pt->head.size && ucmpv64(now64, &pt->info[0].ttime) <= 0)) {
		errno = ERANGE;
		return FALSE;
	}

	ntpcal_ntp64_to_date(&fts, now64);
	/* To guard against dangling leap flags: do not accept leap
	 * second request on the 1st hour of the 1st day of the month.
	 */
	if (fts.monthday == 1 && fts.hour == 0) {
		errno = EINVAL;
		return FALSE;
	}

	/* Ok, do the remaining calculations */
	fts.monthday = 1;
	fts.hour     = 0;
	fts.minute   = 0;
	fts.second   = 0;
	stime = ntpcal_date_to_ntp64(&fts);
	fts.month++;
	ttime = ntpcal_date_to_ntp64(&fts);

	li.ttime = ttime;
	li.stime = ttime.D_s.lo - stime.D_s.lo;
	li.taiof = (pt->head.size ? pt->info[0].taiof : pt->head.base_tai)
	         + (insert ? 1 : -1);
	li.dynls = 1;
	return add_range(pt, &li);
}
Ejemplo n.º 4
0
/* [internal] Given a time stamp for a leap insertion (the exact begin
 * of the new leap era), create new leap frame and put it into the
 * table. This is the work horse for reading a leap file and getting a
 * leap second update via authenticated network packet.
 */
int/*BOOL*/
leapsec_raw(
	leap_table_t * pt,
	const vint64 * ttime,
	int            taiof,
	int            dynls)
{
	vint64		starttime;
	struct calendar	fts;
	leap_info_t	li;

	/* Check that we either extend the table or get a duplicate of
	 * the latest entry. The latter is a benevolent overwrite with
	 * identical data and could happen if we get an autokey message
	 * that extends the lifetime of the current leapsecond table.
	 * Otherwise paranoia rulez!
	 */
	if (pt->head.size) {
		int cmp = ucmpv64(ttime, &pt->info[0].ttime);
		if (cmp == 0)
			cmp -= (taiof != pt->info[0].taiof);
		if (cmp < 0) {
			errno = ERANGE;
			return FALSE;
		}
		if (cmp == 0)
			return TRUE;
	}

	ntpcal_ntp64_to_date(&fts, ttime);
	/* If this does not match the exact month start, bail out. */
	if (fts.monthday != 1 || fts.hour || fts.minute || fts.second) {
		errno = EINVAL;
		return FALSE;
	}
	fts.month--; /* was in range 1..12, no overflow here! */
	starttime = ntpcal_date_to_ntp64(&fts);
	li.ttime = *ttime;
	li.stime = ttime->D_s.lo - starttime.D_s.lo;
	li.taiof = (int16_t)taiof;
	li.dynls = (dynls != 0);
	return add_range(pt, &li);
}
Ejemplo n.º 5
0
/* ---------------------------------------------------------------------
 * Load a leap second file and check expiration on the go
 */
int/*BOOL*/
leapsec_load(
	leap_table_t * pt  ,
	leapsec_reader func,
	void *         farg,
	int            use_build_limit)
{
	char   *cp, *ep, linebuf[50];
	vint64 ttime, limit;
	long   taiof;
	struct calendar build;

	leapsec_clear(pt);
	if (use_build_limit && ntpcal_get_build_date(&build))
		limit = ntpcal_date_to_ntp64(&build);
	else
		memset(&limit, 0, sizeof(limit));

	while (get_line(func, farg, linebuf, sizeof(linebuf))) {
		cp = linebuf;
		if (*cp == '#') {
			cp++;
			if (*cp == '@') {
				cp = skipws(cp+1);
				pt->head.expire = strtouv64(cp, &ep, 10);
				if (parsefail(cp, ep))
					goto fail_read;
				pt->lsig.etime = pt->head.expire.D_s.lo;
			} else if (*cp == '$') {
				cp = skipws(cp+1);
				pt->head.update = strtouv64(cp, &ep, 10);
				if (parsefail(cp, ep))
					goto fail_read;
			}		    
		} else if (isdigit((u_char)*cp)) {
			ttime = strtouv64(cp, &ep, 10);
			if (parsefail(cp, ep))
				goto fail_read;
			cp = skipws(ep);
			taiof = strtol(cp, &ep, 10);
			if (   parsefail(cp, ep)
			    || taiof > SHRT_MAX || taiof < SHRT_MIN)
				goto fail_read;
			if (ucmpv64(&ttime, &limit) >= 0) {
				if (!leapsec_raw(pt, &ttime,
						 taiof, FALSE))
					goto fail_insn;
			} else {
				pt->head.base_tai = (int16_t)taiof;
			}
			pt->lsig.ttime = ttime.D_s.lo;
			pt->lsig.taiof = (int16_t)taiof;
		}
	}
	return TRUE;

fail_read:
	errno = EILSEQ;
fail_insn:
	leapsec_clear(pt);
	return FALSE;
}
Ejemplo n.º 6
0
/* ---------------------------------------------------------------------
 * Load a leap second file and check expiration on the go
 */
bool
leapsec_load(
	leap_table_t * pt  ,
	leapsec_reader func,
	void *         farg,
	int            use_build_limit)
{
	char   *cp, *ep, linebuf[50];
	time64_t ttime, limit;
	long   taiof;
	struct calendar build;

	leapsec_clear(pt);
	if (use_build_limit && ntpcal_get_build_date(&build))
		limit = ntpcal_date_to_ntp64(&build);
	else
		memset(&limit, 0, sizeof(limit));

	while (get_line(func, farg, linebuf, sizeof(linebuf))) {
		cp = linebuf;
		if (*cp == '#') {
			cp++;
			if (*cp == '@') {
				cp = skipws(cp+1);
				settime64u(pt->head.expire, strtoull(cp, &ep, 10));
				if (parsefail(cp, ep))
					goto fail_read;
				pt->lsig.etime = time64lo(pt->head.expire);
			} else if (*cp == '$') {
				cp = skipws(cp+1);
				settime64u(pt->head.update, strtoull(cp, &ep, 10));
				if (parsefail(cp, ep))
					goto fail_read;
			}		    
		} else if (isdigit((uint8_t)*cp)) {
		    settime64u(ttime, strtoull(cp, &ep, 10));
			if (parsefail(cp, ep))
				goto fail_read;
			cp = skipws(ep);
			taiof = strtol(cp, &ep, 10);
			if (   parsefail(cp, ep)
			    || taiof > SHRT_MAX || taiof < SHRT_MIN)
				goto fail_read;
			if (ttime >= limit) {
				if (!leapsec_raw(pt, ttime,
						 taiof, false))
					goto fail_insn;
			} else {
				pt->head.base_tai = (int16_t)taiof;
			}
			pt->lsig.ttime = time64lo(ttime);
			pt->lsig.taiof = (int16_t)taiof;
		}
	}
	return true;

fail_read:
	errno = EILSEQ;
fail_insn:
	leapsec_clear(pt);
	return false;
}