Beispiel #1
0
void
test_LocalClock(void) {
#ifdef REFCLOCK		/* clockname() is useless otherwise */
	/* We test with a refclock address of type LOCALCLOCK.
	 * with id 8
	 */
	u_int32 addr = REFCLOCK_ADDR;
	addr |= REFCLK_LOCALCLOCK << 8;
	addr |= 0x8;

	sockaddr_u address;
	address.sa4.sin_family = AF_INET;
	address.sa4.sin_addr.s_addr = htonl(addr);
	
	char stringStart[100]= "";

	strcat(stringStart, clockname(REFCLK_LOCALCLOCK));
	strcat(stringStart, "(8)");

	char * expected = stringStart;

	TEST_ASSERT_EQUAL_STRING(expected, refnumtoa(&address));
#else	
	TEST_IGNORE_MESSAGE("REFCLOCK NOT DEFINED, SKIPPING TEST");
#endif	/* REFCLOCK */
}
Beispiel #2
0
/*
 * nntohost - convert network number to host name.  This routine enforces
 *	       the showhostnames setting.
 */
const char *
nntohost(
	sockaddr_u *netnum
	)
{
	if (!showhostnames || SOCK_UNSPEC(netnum))
		return stoa(netnum);
	else if (ISREFCLOCKADR(netnum))
		return refnumtoa(netnum);
	else
		return socktohost(netnum);
}
Beispiel #3
0
/*
 * nntohost - convert network number to host name.  This routine enforces
 *	       the showhostnames setting.
 */
char *
nntohost(
	sockaddr_u *netnum
	)
{
	if (!showhostnames)
		return stoa(netnum);

	if (ISREFCLOCKADR(netnum))
		return refnumtoa(netnum);
	return socktohost(netnum);
}
/*
 * refclock_report - note the occurance of an event
 *
 * This routine presently just remembers the report and logs it, but
 * does nothing heroic for the trap handler. It tries to be a good
 * citizen and bothers the system log only if things change.
 */
void
refclock_report(
	struct peer *peer,
	int code
	)
{
	struct refclockproc *pp;

	if (!(pp = peer->procptr))
		return;
	if (code == CEVNT_BADREPLY)
		pp->badformat++;
	if (code == CEVNT_BADTIME)
		pp->baddata++;
	if (code == CEVNT_TIMEOUT)
		pp->noreply++;
	if (pp->currentstatus != code) {
		pp->currentstatus = code;
		pp->lastevent = code;
		if (code == CEVNT_FAULT)
			msyslog(LOG_ERR,
				"clock %s event '%s' (0x%02x)",
				refnumtoa(peer->srcadr.sin_addr.s_addr),
				ceventstr(code), code);
		else {
			NLOG(NLOG_CLOCKEVENT)
				msyslog(LOG_INFO,
				"clock %s event '%s' (0x%02x)",
				refnumtoa(peer->srcadr.sin_addr.s_addr),
				ceventstr(code), code);
		}
	}
#ifdef DEBUG
	if (debug)
		printf("clock %s event '%s' (0x%02x)\n",
			refnumtoa(peer->srcadr.sin_addr.s_addr),
			ceventstr(code), code);
#endif
}
Beispiel #5
0
    /* We test with a refclock address of type LOCALCLOCK.
     * with id 8
     */
    u_int32 addr = REFCLOCK_ADDR;
    addr |= REFCLK_LOCALCLOCK << 8;
    addr |= 0x8;

    sockaddr_u address;
    address.sa4.sin_family = AF_INET;
    address.sa4.sin_addr.s_addr = htonl(addr);

    std::ostringstream expected;
    expected << clockname(REFCLK_LOCALCLOCK)
             << "(8)";

    EXPECT_STREQ(expected.str().c_str(), refnumtoa(&address));
}
#endif	/* REFCLOCK */

#ifdef REFCLOCK		/* refnumtoa() is useless otherwise */
TEST_F(refnumtoaTest, UnknownId) {
    /* We test with a currently unused refclock ID */
    u_int32 addr = REFCLOCK_ADDR;
    addr |= UNUSED_REFCLOCK_ID << 8;
    addr |= 0x4;

    sockaddr_u address;
    address.sa4.sin_family = AF_INET;
    address.sa4.sin_addr.s_addr = htonl(addr);

    std::ostringstream expected;
    expected << "REFCLK(" << UNUSED_REFCLOCK_ID
             << ",4)";

    EXPECT_STREQ(expected.str().c_str(), refnumtoa(&address));
}
Beispiel #6
0
    /* Might need to be updated if a new refclock gets this id. */
    static const int UNUSED_REFCLOCK_ID = 250;
};

#ifdef REFCLOCK		/* clockname() is useless otherwise */
TEST_F(refnumtoaTest, LocalClock) {
    /* We test with a refclock address of type LOCALCLOCK.
     * with id 8
     */
    u_int32 addr = REFCLOCK_ADDR;
    addr |= REFCLK_LOCALCLOCK << 8;
    addr |= 0x8;

    sockaddr_u address;
    address.sa4.sin_family = AF_INET;
    address.sa4.sin_addr.s_addr = htonl(addr);

    std::ostringstream expected;
    expected << clockname(REFCLK_LOCALCLOCK)
             << "(8)";

    EXPECT_STREQ(expected.str().c_str(), refnumtoa(&address));
}
Beispiel #7
0
static void
wwvb_control(
	int unit,
	struct refclockstat *in_st,
	struct refclockstat *out_st,
	struct peer *peer
	)
{
	register struct wwvbunit *up;
	struct refclockproc *pp;
	
	pp = peer->procptr;
	up = pp->unitptr;

	if (!(pp->sloppyclockflag & CLK_FLAG1)) {
		if (!up->ppsapi_tried)
			return;
		up->ppsapi_tried = 0;
		if (!up->ppsapi_lit)
			return;
		peer->flags &= ~FLAG_PPS;
		peer->precision = PRECISION;
		time_pps_destroy(up->atom.handle);
		up->atom.handle = 0;
		up->ppsapi_lit = 0;
		return;
	}

	if (up->ppsapi_tried)
		return;
	/*
	 * Light up the PPSAPI interface.
	 */
	up->ppsapi_tried = 1;
	if (refclock_ppsapi(pp->io.fd, &up->atom)) {
		up->ppsapi_lit = 1;
		return;
	}

	NLOG(NLOG_CLOCKINFO)
		msyslog(LOG_WARNING, "%s flag1 1 but PPSAPI fails",
			refnumtoa(&peer->srcadr));
}
Beispiel #8
0
static void
gpsd_shutdown(
	int     unit,
	peerT * peer)
{
	clockprocT * const pp = peer->procptr;
	gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;

	UNUSED_ARG(unit);

	if (up) {
	    free(up->device);
	    free(up);
	}
	pp->unitptr = (caddr_t)NULL;
	if (-1 != pp->io.fd)
		io_closeclock(&pp->io);
	pp->io.fd = -1;
	LOGIF(CLOCKINFO,
	      (LOG_NOTICE, "%s: shutdown", refnumtoa(&peer->srcadr)));
}
Beispiel #9
0
static void
gpsd_stop_socket(
	peerT * const peer)
{
	clockprocT * const pp = peer->procptr;
	gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;

	if (-1 != pp->io.fd)
		io_closeclock(&pp->io);
	pp->io.fd = -1;
	if (syslogok(pp, up))
		msyslog(LOG_INFO,
			"%s: closing socket to GPSD",
			refnumtoa(&peer->srcadr));
	up->tickover = up->tickpres;
	up->tickpres = min(up->tickpres + 5, TICKOVER_HIGH);
	up->fl_vers  = 0;
	up->fl_tpv   = 0;
	up->fl_pps   = 0;
	up->fl_watch = 0;
}
Beispiel #10
0
void test_UnknownId() {
#ifdef REFCLOCK		/* refnumtoa() is useless otherwise */
	/* We test with a currently unused refclock ID */
	u_int32 addr = REFCLOCK_ADDR;
	addr |= UNUSED_REFCLOCK_ID << 8;
	addr |= 0x4;

	sockaddr_u address;
	address.sa4.sin_family = AF_INET;
	address.sa4.sin_addr.s_addr = htonl(addr);
	
	char stringStart [100]= "REFCLK(";
	char value [100] ;	
	snprintf(value, sizeof(value), "%d", UNUSED_REFCLOCK_ID);
	strcat(stringStart,value);
	strcat(stringStart,",4)");
	char * expected = stringStart;

	TEST_ASSERT_EQUAL_STRING(expected, refnumtoa(&address));
#else 	
	TEST_IGNORE_MESSAGE("REFCLOCK NOT DEFINED, SKIPPING TEST");
#endif	/* REFCLOCK */
}
Beispiel #11
0
/*
 * refclock_report - note the occurance of an event
 *
 * This routine presently just remembers the report and logs it, but
 * does nothing heroic for the trap handler. It tries to be a good
 * citizen and bothers the system log only if things change.
 */
void
refclock_report(
	struct peer *peer,
	int code
	)
{
	struct refclockproc *pp;

	pp = peer->procptr;
	if (pp == NULL)
		return;

	switch (code) {
		case CEVNT_NOMINAL:
			break;

		case CEVNT_TIMEOUT:
			pp->noreply++;
			break;

		case CEVNT_BADREPLY:
			pp->badformat++;
			break;

		case CEVNT_FAULT:
			break;

		case CEVNT_PROP:
			break;

		case CEVNT_BADDATE:
		case CEVNT_BADTIME:
			pp->baddata++;
			break;

		default:
			/* shouldn't happen */
			break;
	}

	if (pp->currentstatus != code) {
		pp->currentstatus = (u_char)code;

		/* RFC1305: copy only iff not CEVNT_NOMINAL */
		if (code != CEVNT_NOMINAL)
			pp->lastevent = (u_char)code;

		if (code == CEVNT_FAULT)
			msyslog(LOG_ERR,
			    "clock %s event '%s' (0x%02x)",
			    refnumtoa(&peer->srcadr),
			    ceventstr(code), code);
		else {
			NLOG(NLOG_CLOCKEVENT)
			  msyslog(LOG_INFO,
			    "clock %s event '%s' (0x%02x)",
			    refnumtoa(&peer->srcadr),
			    ceventstr(code), code);
		}

		/* RFC1305: post peer clock event */
		report_event(EVNT_PEERCLOCK, peer);
	}
}
Beispiel #12
0
/*
 * Decode an incoming data buffer and print a line in the peer list
 */
static int
doprintpeers(
	struct varlist *pvl,
	int associd,
	int rstatus,
	int datalen,
	const char *data,
	FILE *fp,
	int af
	)
{
	char *name;
	char *value = NULL;
	int i;
	int c;

	sockaddr_u srcadr;
	sockaddr_u dstadr;
	sockaddr_u refidadr;
	u_long srcport = 0;
	char *dstadr_refid = "0.0.0.0";
	char *serverlocal;
	size_t drlen;
	u_long stratum = 0;
	long ppoll = 0;
	long hpoll = 0;
	u_long reach = 0;
	l_fp estoffset;
	l_fp estdelay;
	l_fp estjitter;
	l_fp estdisp;
	l_fp reftime;
	l_fp rec;
	l_fp ts;
	u_char havevar[MAXHAVE];
	u_long poll_sec;
	char type = '?';
	char refid_string[10];
	char whenbuf[8], pollbuf[8];
	char clock_name[LENHOSTNAME];

	memset((char *)havevar, 0, sizeof(havevar));
	get_systime(&ts);
	
	ZERO_SOCK(&srcadr);
	ZERO_SOCK(&dstadr);

	/* Initialize by zeroing out estimate variables */
	memset((char *)&estoffset, 0, sizeof(l_fp));
	memset((char *)&estdelay, 0, sizeof(l_fp));
	memset((char *)&estjitter, 0, sizeof(l_fp));
	memset((char *)&estdisp, 0, sizeof(l_fp));

	while (nextvar(&datalen, &data, &name, &value)) {
		sockaddr_u dum_store;

		i = findvar(name, peer_var, 1);
		if (i == 0)
			continue;	/* don't know this one */
		switch (i) {
			case CP_SRCADR:
			if (decodenetnum(value, &srcadr)) {
				havevar[HAVE_SRCADR] = 1;
			}
			break;
			case CP_DSTADR:
			if (decodenetnum(value, &dum_store)) {
				type = decodeaddrtype(&dum_store);
				havevar[HAVE_DSTADR] = 1;
				dstadr = dum_store;
				if (pvl == opeervarlist) {
					dstadr_refid = trunc_left(stoa(&dstadr), 15);
				}
			}
			break;
			case CP_REFID:
			if (pvl == peervarlist) {
				havevar[HAVE_REFID] = 1;
				if (*value == '\0') {
					dstadr_refid = "";
				} else if (strlen(value) <= 4) {
					refid_string[0] = '.';
					(void) strcpy(&refid_string[1], value);
					i = strlen(refid_string);
					refid_string[i] = '.';
					refid_string[i+1] = '\0';
					dstadr_refid = refid_string;
				} else if (decodenetnum(value, &refidadr)) {
					if (SOCK_UNSPEC(&refidadr))
						dstadr_refid = "0.0.0.0";
					else if (ISREFCLOCKADR(&refidadr))
						dstadr_refid =
						    refnumtoa(&refidadr);
					else
						dstadr_refid =
						    stoa(&refidadr);
				} else {
					havevar[HAVE_REFID] = 0;
				}
			}
			break;
			case CP_STRATUM:
			if (decodeuint(value, &stratum))
				havevar[HAVE_STRATUM] = 1;
			break;
			case CP_HPOLL:
			if (decodeint(value, &hpoll)) {
				havevar[HAVE_HPOLL] = 1;
				if (hpoll < 0)
					hpoll = NTP_MINPOLL;
			}
			break;
			case CP_PPOLL:
			if (decodeint(value, &ppoll)) {
				havevar[HAVE_PPOLL] = 1;
				if (ppoll < 0)
					ppoll = NTP_MINPOLL;
			}
			break;
			case CP_REACH:
			if (decodeuint(value, &reach))
				havevar[HAVE_REACH] = 1;
			break;
			case CP_DELAY:
			if (decodetime(value, &estdelay))
				havevar[HAVE_DELAY] = 1;
			break;
			case CP_OFFSET:
			if (decodetime(value, &estoffset))
				havevar[HAVE_OFFSET] = 1;
			break;
			case CP_JITTER:
			if (pvl == peervarlist)
				if (decodetime(value, &estjitter))
					havevar[HAVE_JITTER] = 1;
			break;
			case CP_DISPERSION:
			if (decodetime(value, &estdisp))
				havevar[HAVE_DISPERSION] = 1;
			break;
			case CP_REC:
			if (decodets(value, &rec))
				havevar[HAVE_REC] = 1;
			break;
			case CP_SRCPORT:
			if (decodeuint(value, &srcport))
				havevar[HAVE_SRCPORT] = 1;
			break;
			case CP_REFTIME:
			havevar[HAVE_REFTIME] = 1;
			if (!decodets(value, &reftime))
				L_CLR(&reftime);
			break;
			default:
			break;
		}
	}

	/*
	 * Check to see if the srcport is NTP's port.  If not this probably
	 * isn't a valid peer association.
	 */
	if (havevar[HAVE_SRCPORT] && srcport != NTP_PORT)
		return (1);

	/*
	 * Got everything, format the line
	 */
	poll_sec = 1<<max(min3(ppoll, hpoll, NTP_MAXPOLL), NTP_MINPOLL);
	if (pktversion > NTP_OLDVERSION)
		c = flash3[CTL_PEER_STATVAL(rstatus) & 0x7];
	else
		c = flash2[CTL_PEER_STATVAL(rstatus) & 0x3];
	if (numhosts > 1) {
		if (peervarlist == pvl && havevar[HAVE_DSTADR]) {
			serverlocal = nntohost_col(&dstadr,
			    (size_t)min(LIB_BUFLENGTH - 1, maxhostlen),
			    TRUE);
		} else {
			if (currenthostisnum)
				serverlocal = trunc_left(currenthost,
							 maxhostlen);
			else
				serverlocal = currenthost;
		}
		fprintf(fp, "%-*s ", maxhostlen, serverlocal);
	}
	if (AF_UNSPEC == af || AF(&srcadr) == af) {
		strncpy(clock_name, nntohost(&srcadr), sizeof(clock_name));		
		fprintf(fp, "%c%-15.15s ", c, clock_name);
		drlen = strlen(dstadr_refid);
		makeascii(drlen, dstadr_refid, fp);
		while (drlen++ < 15)
			fputc(' ', fp);
		fprintf(fp,
			" %2ld %c %4.4s %4.4s  %3lo  %7.7s %8.7s %7.7s\n",
			stratum, type,
			prettyinterval(whenbuf, sizeof(whenbuf),
				       when(&ts, &rec, &reftime)),
			prettyinterval(pollbuf, sizeof(pollbuf), 
				       (int)poll_sec),
			reach, lfptoms(&estdelay, 3),
			lfptoms(&estoffset, 3),
			(havevar[HAVE_JITTER])
			    ? lfptoms(&estjitter, 3)
			    : lfptoms(&estdisp, 3));
		return (1);
	}
	else
		return(1);
}
Beispiel #13
0
static void
gpsd_test_socket(
	peerT * const peer)
{
	clockprocT * const pp = peer->procptr;
	gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;

	int       ec, rc;
	socklen_t lc;

	/* Check if the non-blocking connect was finished by testing the
	 * socket for writeability. Use the 'poll()' API if available
	 * and 'select()' otherwise.
	 */
	DPRINTF(2, ("GPSD_JSON(%d): check connect, fd=%d\n",
		    up->unit, up->fdt));

#if defined(HAVE_SYS_POLL_H)
	{
		struct pollfd pfd;

		pfd.events = POLLOUT;
		pfd.fd     = up->fdt;
		rc = poll(&pfd, 1, 0);
		if (1 != rc || !(pfd.revents & POLLOUT))
			return;
	}
#elif defined(HAVE_SYS_SELECT_H)
	{
		struct timeval tout;
		fd_set         wset;

		memset(&tout, 0, sizeof(tout));
		FD_ZERO(&wset);
		FD_SET(up->fdt, &wset);
		rc = select(up->fdt+1, NULL, &wset, NULL, &tout);
		if (0 == rc || !(FD_ISSET(up->fdt, &wset)))
			return;
	}
#else
# error Blooper! That should have been found earlier!
#endif

	/* next timeout is a full one... */
	up->tickover = TICKOVER_LOW;

	/* check for socket error */
	ec = 0;
	lc = sizeof(ec);
	rc = getsockopt(up->fdt, SOL_SOCKET, SO_ERROR, &ec, &lc);
	DPRINTF(1, ("GPSD_JSON(%d): connect finshed, fd=%d, ec=%d(%s)\n",
		    up->unit, up->fdt, ec, strerror(ec)));
	if (-1 == rc || 0 != ec) {
		errno = ec;
		if (syslogok(pp, up))
			msyslog(LOG_ERR,
				"%s: (async)cannot connect GPSD socket: %m",
				refnumtoa(&peer->srcadr));
		goto no_socket;
	}	
	/* swap socket FDs, and make sure the clock was added */
	pp->io.fd = up->fdt;
	up->fdt   = -1;
	if (0 == io_addclock(&pp->io)) {
		if (syslogok(pp, up))
			msyslog(LOG_ERR,
				"%s: failed to register with I/O engine",
				refnumtoa(&peer->srcadr));
		goto no_socket;
	}
	return;
	
  no_socket:
	if (-1 != up->fdt)
		close(up->fdt);
	up->fdt      = -1;
	up->tickover = up->tickpres;
	up->tickpres = min(up->tickpres + 5, TICKOVER_HIGH);
}
Beispiel #14
0
static int
gpsd_start(
	int     unit,
	peerT * peer)
{
	clockprocT * const pp = peer->procptr;
	gpsd_unitT * const up = emalloc_zero(sizeof(*up));

	struct stat sb;

	/* initialize the unit structure */
	up->fdt      = -1;
	up->addr     = s_gpsd_addr;
	up->tickpres = TICKOVER_LOW;

	/* setup refclock processing */
	up->unit    = unit;
	pp->unitptr = (caddr_t)up;
	pp->io.fd   = -1;
	pp->io.clock_recv = gpsd_receive;
	pp->io.srcclock   = peer;
	pp->io.datalen    = 0;
	pp->a_lastcode[0] = '\0';
	pp->lencode       = 0;
	pp->clockdesc     = DESCRIPTION;
	memcpy(&pp->refid, REFID, 4);

	/* Initialize miscellaneous variables */
	peer->precision = PRECISION;

	/* Create the device name and check for a Character Device. It's
	 * assumed that GPSD was started with the same link, so the
	 * names match. (If this is not practicable, we will have to
	 * read the symlink, if any, so we can get the true device
	 * file.)
	 */
	if (-1 == myasprintf(&up->device, "%s%u", s_dev_stem, unit)) {
	    msyslog(LOG_ERR, "%s clock device name too long",
		    refnumtoa(&peer->srcadr));
	    goto dev_fail;
	}
	if (-1 == stat(up->device, &sb) || !S_ISCHR(sb.st_mode)) {
		msyslog(LOG_ERR, "%s: '%s' is not a character device",
			refnumtoa(&peer->srcadr), up->device);
	    goto dev_fail;
	}
	LOGIF(CLOCKINFO,
	      (LOG_NOTICE, "%s: startup, device is '%s'",
	       refnumtoa(&peer->srcadr), up->device));
	return TRUE;

dev_fail:
	/* On failure, remove all UNIT ressources and declare defeat. */

	INSIST (up);
	free(up->device);
	free(up);

	pp->unitptr = (caddr_t)NULL;
	return FALSE;
}
Beispiel #15
0
static void
process_version(
	peerT      * const peer ,
	json_ctx   * const jctx ,
	const l_fp * const rtime)
{
	clockprocT * const pp = peer->procptr;
	gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;

	int    len;
	char * buf;
	const char *revision;
	const char *release;

	/* get protocol version number */
	revision = json_object_lookup_string_default(
	    jctx, 0, "rev", "(unknown)");
	release  = json_object_lookup_string_default(
	    jctx, 0, "release", "(unknown)");
	errno = 0;
	up->proto_major = (uint16_t)json_object_lookup_int(
		jctx, 0, "proto_major");
	up->proto_minor = (uint16_t)json_object_lookup_int(
		jctx, 0, "proto_minor");
	if (0 == errno) {
		up->fl_vers = -1;
		if (syslogok(pp, up))
			msyslog(LOG_INFO,
				"%s: GPSD revision=%s release=%s protocol=%u.%u",
				refnumtoa(&peer->srcadr),
				revision, release,
				up->proto_major, up->proto_minor);
	}

	/* With the 3.9 GPSD protocol, '*_musec' vanished and was
	 * replace by '*_nsec'. Dispatch properly.
	 */
	if ( up->proto_major >  3 ||
	    (up->proto_major == 3 && up->proto_minor >= 9))
		up->fl_nsec = -1;
	else
		up->fl_nsec = 0;

	/*TODO: validate protocol version! */
	
	/* request watch for our GPS device
	 * Reuse the input buffer, which is no longer needed in the
	 * current cycle. Also assume that we can write the watch
	 * request in one sweep into the socket; since we do not do
	 * output otherwise, this should always work.  (Unless the
	 * TCP/IP window size gets lower than the length of the
	 * request. We handle that when it happens.)
	 */
	snprintf(up->buffer, sizeof(up->buffer),
		 s_logon, up->device);
	buf = up->buffer;
	len = strlen(buf);
	if (len != write(pp->io.fd, buf, len)) {
		/*Note: if the server fails to read our request, the
		 * resulting data timeout will take care of the
		 * connection!
		 */
		if (syslogok(pp, up))
			msyslog(LOG_ERR,
				"%s: failed to write watch request (%m)",
				refnumtoa(&peer->srcadr));
	}
}
Beispiel #16
0
/*
 * shm_timer - called once every second.
 *
 * This tries to grab a sample from the SHM segment, filtering bad ones
 */
static void
shm_timer(
	int unit,
	struct peer *peer
	)
{
	struct refclockproc * const pp = peer->procptr;
	struct shmunit *      const up = pp->unitptr;

	volatile struct shmTime *shm;

	l_fp tsrcv;
	l_fp tsref;
	int c;

	/* for formatting 'a_lastcode': */
	struct calendar cd;
	time_t tt;
	vint64 ts;

	enum segstat_t status;
	struct shm_stat_t shm_stat;

	up->ticks++;
	if ((shm = up->shm) == NULL) {
		/* try to map again - this may succeed if meanwhile some-
		body has ipcrm'ed the old (unaccessible) shared mem segment */
		shm = up->shm = getShmTime(unit, up->forall);
		if (shm == NULL) {
			DPRINTF(1, ("%s: no SHM segment\n",
				    refnumtoa(&peer->srcadr)));
			return;
		}
	}

	/* query the segment, atomically */
	status = shm_query(shm, &shm_stat);

	switch (status) {
	case OK:
	    DPRINTF(2, ("%s: SHM type %d sample\n",
			refnumtoa(&peer->srcadr), shm_stat.mode));
	    break;
	case NO_SEGMENT:
	    /* should never happen, but is harmless */
	    return;
	case NOT_READY:
	    DPRINTF(1, ("%s: SHM not ready\n",refnumtoa(&peer->srcadr)));
	    up->notready++;
	    return;
	case BAD_MODE:
	    DPRINTF(1, ("%s: SHM type blooper, mode=%d\n",
			refnumtoa(&peer->srcadr), shm->mode));
	    up->bad++;
	    msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",
		     shm->mode);
	    return;
	case CLASH:
	    DPRINTF(1, ("%s: type 1 access clash\n",
			refnumtoa(&peer->srcadr)));
	    msyslog (LOG_NOTICE, "SHM: access clash in shared memory");
	    up->clash++;
	    return;
	default:
	    DPRINTF(1, ("%s: internal error, unknown SHM fetch status\n",
			refnumtoa(&peer->srcadr)));
	    msyslog (LOG_NOTICE, "internal error, unknown SHM fetch status");
	    up->bad++;
	    return;
	}


	/* format the last time code in human-readable form into
	 * 'pp->a_lastcode'. Someone claimed: "NetBSD has incompatible
	 * tv_sec". I can't find a base for this claim, but we can work
	 * around that potential problem. BTW, simply casting a pointer
	 * is a receipe for disaster on some architectures.
	 */
	tt = (time_t)shm_stat.tvt.tv_sec;
	ts = time_to_vint64(&tt);
	ntpcal_time_to_date(&cd, &ts);
		
	/* add ntpq -c cv timecode in ISO 8601 format */
	c = snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
		     "%04u-%02u-%02uT%02u:%02u:%02u.%09ldZ",
		     cd.year, cd.month, cd.monthday,
		     cd.hour, cd.minute, cd.second,
		     (long)shm_stat.tvt.tv_nsec);
	pp->lencode = ((size_t)c < sizeof(pp->a_lastcode)) ? c : 0;

	/* check 1: age control of local time stamp */
	tt = shm_stat.tvc.tv_sec - shm_stat.tvr.tv_sec;
	if (tt < 0 || tt > up->max_delay) {
		DPRINTF(1, ("%s:SHM stale/bad receive time, delay=%llds\n",
			    refnumtoa(&peer->srcadr), (long long)tt));
		up->bad++;
		msyslog (LOG_ERR, "SHM: stale/bad receive time, delay=%llds",
			 (long long)tt);
		return;
	}

	/* check 2: delta check */
	tt = shm_stat.tvr.tv_sec - shm_stat.tvt.tv_sec - (shm_stat.tvr.tv_nsec < shm_stat.tvt.tv_nsec);
	if (tt < 0)
		tt = -tt;
	if (up->max_delta > 0 && tt > up->max_delta) {
		DPRINTF(1, ("%s: SHM diff limit exceeded, delta=%llds\n",
			    refnumtoa(&peer->srcadr), (long long)tt));
		up->bad++;
		msyslog (LOG_ERR, "SHM: difference limit exceeded, delta=%llds\n",
			 (long long)tt);
		return;
	}

	/* if we really made it to this point... we're winners! */
	DPRINTF(2, ("%s: SHM feeding data\n",
		    refnumtoa(&peer->srcadr)));
	tsrcv = tspec_stamp_to_lfp(shm_stat.tvr);
	tsref = tspec_stamp_to_lfp(shm_stat.tvt);
	pp->leap = shm_stat.leap;
	peer->precision = shm_stat.precision;
	refclock_process_offset(pp, tsref, tsrcv, pp->fudgetime1);
	up->good++;
}
Beispiel #17
0
static void
gpsd_init_socket(
	peerT * const peer)
{
	clockprocT * const pp = peer->procptr;
	gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
	addrinfoT  * ai;
	int          rc;
	int          ov;

	/* draw next address to try */
	if (NULL == up->addr)
		up->addr = s_gpsd_addr;
	ai = up->addr;
	up->addr = ai->ai_next;

	/* try to create a matching socket */
	up->fdt = socket(
		ai->ai_family, ai->ai_socktype, ai->ai_protocol);
	if (-1 == up->fdt) {
		if (syslogok(pp, up))
			msyslog(LOG_ERR,
				"%s: cannot create GPSD socket: %m",
				refnumtoa(&peer->srcadr));
		goto no_socket;
	}
	
	/* make sure the socket is non-blocking */
	rc = fcntl(up->fdt, F_SETFL, O_NONBLOCK, 1);
	if (-1 == rc) {
		if (syslogok(pp, up))
			msyslog(LOG_ERR,
				"%s: cannot set GPSD socket to non-blocking: %m",
				refnumtoa(&peer->srcadr));
		goto no_socket;
	}
	/* disable nagling */
	ov = 1;
	rc = setsockopt(up->fdt, IPPROTO_TCP, TCP_NODELAY,
			(char*)&ov, sizeof(ov));
	if (-1 == rc) {
		if (syslogok(pp, up))
			msyslog(LOG_INFO,
				"%s: cannot disable TCP nagle: %m",
				refnumtoa(&peer->srcadr));
	}

	/* start a non-blocking connect */
	rc = connect(up->fdt, ai->ai_addr, ai->ai_addrlen);
	if (-1 == rc && errno != EINPROGRESS) {
		if (syslogok(pp, up))
			msyslog(LOG_ERR,
				"%s: cannot connect GPSD socket: %m",
				refnumtoa(&peer->srcadr));
		goto no_socket;
	}

	return;
  
  no_socket:
	if (-1 != up->fdt)
		close(up->fdt);
	up->fdt      = -1;
	up->tickover = up->tickpres;
	up->tickpres = min(up->tickpres + 5, TICKOVER_HIGH);
}