aboutsummaryrefslogtreecommitdiff
path: root/ntpd/refclock_shm.c
diff options
context:
space:
mode:
authorOllivier Robert <roberto@FreeBSD.org>2013-12-04 21:33:17 +0000
committerOllivier Robert <roberto@FreeBSD.org>2013-12-04 21:33:17 +0000
commit2b45e011ca352ce509bc83ae148230aeee0c7e0d (patch)
treea618007bb41d13153794a598e3d904ace2976324 /ntpd/refclock_shm.c
parent9b5bd0a264b0a21eefac2b929b574c73bd601507 (diff)
downloadsrc-2b45e011ca352ce509bc83ae148230aeee0c7e0d.tar.gz
src-2b45e011ca352ce509bc83ae148230aeee0c7e0d.zip
Virgin import of ntpd 4.2.6p5.vendor/ntp/4.2.6p5
When the series of commits is complete, things like https://cert.litnet.lt/en/docs/ntp-distributed-reflection-dos-attacks should be fixed. PR: bin/148836 (except that we import a newer version) Asked by: Too many MFC after: 2 weeks
Notes
Notes: svn path=/vendor/ntp/dist/; revision=258945 svn path=/vendor/ntp/4.2.6p5/; revision=258946; tag=vendor/ntp/4.2.6p5
Diffstat (limited to 'ntpd/refclock_shm.c')
-rw-r--r--ntpd/refclock_shm.c215
1 files changed, 160 insertions, 55 deletions
diff --git a/ntpd/refclock_shm.c b/ntpd/refclock_shm.c
index 7be263d1ba33..b73e899766d3 100644
--- a/ntpd/refclock_shm.c
+++ b/ntpd/refclock_shm.c
@@ -39,6 +39,9 @@
* This driver supports a reference clock attached thru shared memory
*/
+/* Temp hack to simplify testing of the old mode. */
+#define OLDWAY 0
+
/*
* SHM interface definitions
*/
@@ -51,9 +54,12 @@
/*
* Function prototypes
*/
-static int shm_start (int, struct peer *);
-static void shm_shutdown (int, struct peer *);
-static void shm_poll (int unit, struct peer *);
+static int shm_start (int unit, struct peer *peer);
+static void shm_shutdown (int unit, struct peer *peer);
+static void shm_poll (int unit, struct peer *peer);
+static void shm_timer (int unit, struct peer *peer);
+ int shm_peek (int unit, struct peer *peer);
+ void shm_clockstats (int unit, struct peer *peer);
/*
* Transfer vector
@@ -61,12 +67,13 @@ static void shm_poll (int unit, struct peer *);
struct refclock refclock_shm = {
shm_start, /* start up driver */
shm_shutdown, /* shut down driver */
- shm_poll, /* transmit poll message */
- noentry, /* not used */
- noentry, /* initialize driver (not used) */
- noentry, /* not used */
- NOFLAGS /* not used */
+ shm_poll, /* transmit poll message */
+ noentry, /* not used: control */
+ noentry, /* not used: init */
+ noentry, /* not used: buginfo */
+ shm_timer, /* once per second */
};
+
struct shmTime {
int mode; /* 0 - if valid set
* use values,
@@ -88,15 +95,30 @@ struct shmTime {
int dummy[10];
};
+struct shmunit {
+ struct shmTime *shm; /* pointer to shared memory segment */
+
+ /* debugging/monitoring counters - reset when printed */
+ int ticks; /* number of attempts to read data*/
+ int good; /* number of valid samples */
+ int notready; /* number of peeks without data ready */
+ int bad; /* number of invalid samples */
+ int clash; /* number of access clashes while reading */
+};
+
+
struct shmTime *getShmTime(int);
struct shmTime *getShmTime (int unit) {
#ifndef SYS_WINNT
int shmid=0;
- assert (unit<10); /* MAXUNIT is 4, so should never happen */
+ /* 0x4e545030 is NTP0.
+ * Big units will give non-ascii but that's OK
+ * as long as everybody does it the same way.
+ */
shmid=shmget (0x4e545030+unit, sizeof (struct shmTime),
- IPC_CREAT|(unit<2?0700:0777));
+ IPC_CREAT|(unit<2?0600:0666));
if (shmid==-1) { /*error */
msyslog(LOG_ERR,"SHM shmget (unit %d): %s",unit,strerror(errno));
return 0;
@@ -115,8 +137,8 @@ struct shmTime *getShmTime (int unit) {
HANDLE shmid=0;
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
- sprintf (buf,"NTP%d",unit);
- if (unit>=2) { /* world access */
+ snprintf(buf, sizeof(buf), "NTP%d", unit);
+ if (unit >= 2) { /* world access */
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
msyslog(LOG_ERR,"SHM InitializeSecurityDescriptor (unit %d): %m",unit);
return 0;
@@ -163,22 +185,29 @@ shm_start(
)
{
struct refclockproc *pp;
+ struct shmunit *up;
+
pp = peer->procptr;
pp->io.clock_recv = noentry;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
pp->io.fd = -1;
- pp->unitptr = (caddr_t)getShmTime(unit);
+
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
+ pp->unitptr = (caddr_t)up;
+
+ up->shm = getShmTime(unit);
/*
* Initialize miscellaneous peer variables
*/
memcpy((char *)&pp->refid, REFID, 4);
- if (pp->unitptr!=0) {
- ((struct shmTime*)pp->unitptr)->precision=PRECISION;
- peer->precision = ((struct shmTime*)pp->unitptr)->precision;
- ((struct shmTime*)pp->unitptr)->valid=0;
- ((struct shmTime*)pp->unitptr)->nsamples=NSAMPLES;
+ if (up->shm != 0) {
+ up->shm->precision = PRECISION;
+ peer->precision = up->shm->precision;
+ up->shm->valid=0;
+ up->shm->nsamples=NSAMPLES;
pp->clockdesc = DESCRIPTION;
return (1);
}
@@ -197,17 +226,34 @@ shm_shutdown(
struct peer *peer
)
{
- register struct shmTime *up;
struct refclockproc *pp;
+ struct shmunit *up;
pp = peer->procptr;
- up = (struct shmTime *)pp->unitptr;
+ up = (struct shmunit *)pp->unitptr;
+
+ if (NULL == up)
+ return;
#ifndef SYS_WINNT
/* HMS: shmdt()wants char* or const void * */
- (void) shmdt (up);
+ (void) shmdt ((char *)up->shm);
#else
- UnmapViewOfFile (up);
+ UnmapViewOfFile (up->shm);
#endif
+ free(up);
+}
+
+
+/*
+ * shm_timer - called every second
+ */
+static void
+shm_timer(int unit, struct peer *peer)
+{
+ if (OLDWAY)
+ return;
+
+ shm_peek(unit, peer);
}
@@ -220,26 +266,60 @@ shm_poll(
struct peer *peer
)
{
- register struct shmTime *up;
struct refclockproc *pp;
+ int ok;
+
+ pp = peer->procptr;
+
+ if (OLDWAY) {
+ ok = shm_peek(unit, peer);
+ if (!ok) return;
+ }
+
+ /*
+ * Process median filter samples. If none received, declare a
+ * timeout and keep going.
+ */
+ if (pp->coderecv == pp->codeproc) {
+ refclock_report(peer, CEVNT_TIMEOUT);
+ shm_clockstats(unit, peer);
+ return;
+ }
+ pp->lastref = pp->lastrec;
+ refclock_receive(peer);
+ shm_clockstats(unit, peer);
+}
+
+/*
+ * shm_peek - try to grab a sample
+ */
+int shm_peek(
+ int unit,
+ struct peer *peer
+ )
+{
+ struct refclockproc *pp;
+ struct shmunit *up;
+ struct shmTime *shm;
/*
* This is the main routine. It snatches the time from the shm
* board and tacks on a local timestamp.
*/
pp = peer->procptr;
- up = (struct shmTime*)pp->unitptr;
- if (up==0) { /* try to map again - this may succeed if meanwhile some-
- body has ipcrm'ed the old (unaccessible) shared mem
- segment */
- pp->unitptr = (caddr_t)getShmTime(unit);
- up = (struct shmTime*)pp->unitptr;
+ up = (struct shmunit*)pp->unitptr;
+ up->ticks++;
+ if (up->shm == 0) {
+ /* try to map again - this may succeed if meanwhile some-
+ body has ipcrm'ed the old (unaccessible) shared mem segment */
+ up->shm = getShmTime(unit);
}
- if (up==0) {
+ shm = up->shm;
+ if (shm == 0) {
refclock_report(peer, CEVNT_FAULT);
- return;
+ return(0);
}
- if (up->valid) {
+ if (shm->valid) {
struct timeval tvr;
struct timeval tvt;
struct tm *t;
@@ -248,27 +328,27 @@ shm_poll(
tvr.tv_usec = 0;
tvt.tv_sec = 0;
tvt.tv_usec = 0;
- switch (up->mode) {
+ switch (shm->mode) {
case 0: {
- tvr.tv_sec=up->receiveTimeStampSec;
- tvr.tv_usec=up->receiveTimeStampUSec;
- tvt.tv_sec=up->clockTimeStampSec;
- tvt.tv_usec=up->clockTimeStampUSec;
+ tvr.tv_sec=shm->receiveTimeStampSec;
+ tvr.tv_usec=shm->receiveTimeStampUSec;
+ tvt.tv_sec=shm->clockTimeStampSec;
+ tvt.tv_usec=shm->clockTimeStampUSec;
}
break;
case 1: {
- int cnt=up->count;
- tvr.tv_sec=up->receiveTimeStampSec;
- tvr.tv_usec=up->receiveTimeStampUSec;
- tvt.tv_sec=up->clockTimeStampSec;
- tvt.tv_usec=up->clockTimeStampUSec;
- ok=(cnt==up->count);
+ int cnt=shm->count;
+ tvr.tv_sec=shm->receiveTimeStampSec;
+ tvr.tv_usec=shm->receiveTimeStampUSec;
+ tvt.tv_sec=shm->clockTimeStampSec;
+ tvt.tv_usec=shm->clockTimeStampUSec;
+ ok=(cnt==shm->count);
}
break;
default:
- msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",up->mode);
+ msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",shm->mode);
}
- up->valid=0;
+ shm->valid=0;
if (ok) {
time_t help; /* XXX NetBSD has incompatible tv_sec */
@@ -283,28 +363,53 @@ shm_poll(
pp->minute=t->tm_min;
pp->second=t->tm_sec;
pp->nsec=tvt.tv_usec * 1000;
- peer->precision=up->precision;
- pp->leap=up->leap;
+ peer->precision=shm->precision;
+ pp->leap=shm->leap;
}
else {
refclock_report(peer, CEVNT_FAULT);
msyslog (LOG_NOTICE, "SHM: access clash in shared memory");
- return;
+ up->clash++;
+ return(0);
}
}
else {
refclock_report(peer, CEVNT_TIMEOUT);
- /*
- msyslog (LOG_NOTICE, "SHM: no new value found in shared memory");
- */
- return;
+ up->notready++;
+ return(0);
}
if (!refclock_process(pp)) {
refclock_report(peer, CEVNT_BADTIME);
- return;
+ up->bad++;
+ return(0);
}
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
+ up->good++;
+ return(1);
+}
+
+/*
+ * shm_clockstats - dump and reset counters
+ */
+void shm_clockstats(
+ int unit,
+ struct peer *peer
+ )
+{
+ struct refclockproc *pp;
+ struct shmunit *up;
+ char logbuf[256];
+
+ pp = peer->procptr;
+ up = (struct shmunit*)pp->unitptr;
+
+ if (!(pp->sloppyclockflag & CLK_FLAG4)) return;
+
+ snprintf(logbuf, sizeof(logbuf), "%3d %3d %3d %3d %3d",
+ up->ticks, up->good, up->notready, up->bad, up->clash);
+ record_clock_stats(&peer->srcadr, logbuf);
+
+ up->ticks = up->good = up->notready =up->bad = up->clash = 0;
+
}
#else