--- attic/backwards.c.orig	2022-12-22 22:08:52.000000000 -0800
+++ attic/backwards.c	2023-12-30 22:12:39.000000000 -0800
@@ -7,6 +7,8 @@
 #include <stdlib.h>
 #include <time.h>
 
+#include "ntp_machine.h"	/* For clock_gettime fallback */
+
 #define UNUSED_ARG(arg)         ((void)(arg))
 
 static void ts_print(struct timespec *ts0, struct timespec *ts1);
--- attic/clocks.c.orig	2023-12-28 20:53:56.000000000 -0800
+++ attic/clocks.c	2023-12-30 22:12:39.000000000 -0800
@@ -9,6 +9,8 @@
 #include <unistd.h>
 
 
+#include "ntp_machine.h"	/* For clock_gettime fallback */
+
 struct table {
   const int type;
   const char* name;
--- attic/cmac-timing.c.orig	2023-12-28 20:53:53.000000000 -0800
+++ attic/cmac-timing.c	2023-12-30 22:12:39.000000000 -0800
@@ -36,6 +36,8 @@
 #include <openssl/params.h> 
 #endif
 
+#include "ntp_machine.h"	/* For clock_gettime fallback */
+
 #define UNUSED_ARG(arg)         ((void)(arg))
 
 
--- attic/digest-timing.c.orig	2023-12-28 20:53:56.000000000 -0800
+++ attic/digest-timing.c	2023-12-30 22:12:39.000000000 -0800
@@ -32,6 +32,8 @@
 #include <openssl/objects.h>
 #include <openssl/ssl.h>
 
+#include "ntp_machine.h"	/* For clock_gettime fallback */
+
 #define UNUSED_ARG(arg)         ((void)(arg))
 
 #ifndef EVP_MD_CTX_new
--- attic/random.c.orig	2023-12-28 20:53:56.000000000 -0800
+++ attic/random.c	2023-12-30 22:12:39.000000000 -0800
@@ -10,6 +10,8 @@
 #include <openssl/opensslv.h>    /* for OPENSSL_VERSION_NUMBER */
 #include <openssl/rand.h>
 
+#include "ntp_machine.h"	/* For clock_gettime fallback */
+
 #define BATCHSIZE 1000000
 #define BILLION 1000000000
 #define HISTSIZE 2500
--- include/ntp_machine.h.orig	2022-12-22 22:08:52.000000000 -0800
+++ include/ntp_machine.h	2023-12-30 22:12:39.000000000 -0800
@@ -13,14 +13,145 @@
 
 #ifndef CLOCK_REALTIME
 /*
- * Pacify platforms that don't have a real clock_gettime(2),
- * notably Mac OS X.
+ * Handle platforms that don't have a real clock_gettime(2),
+ * notably some versions of Mac OS X.
  */
-#define CLOCK_REALTIME	0
-#define CLOCK_MONOTONIC	1
+
+#include <errno.h>
+
 typedef int clockid_t;
-int clock_gettime(clockid_t clock_id, struct timespec *tp);
-#endif
+
+#define CLOCK_REALTIME	0
+
+#ifdef __APPLE__
+
+#define CLOCK_MONOTONIC 1
+#define CLOCK_MONOTONIC_RAW 2
+
+#include <mach/clock.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+
+#endif /* __APPLE__ */
+
+static inline int clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+    switch (clk_id) {
+
+    case CLOCK_REALTIME:
+	{
+	    /*
+	     * On OSX, it's tempting to use clock_get_time() for its apparent
+	     * nanosecond resolution, but it really only has microsecond
+	     * resolution, and is substantially slower than gettimeofday().
+	     */
+	    struct timeval tv;
+
+	    if (gettimeofday(&tv, NULL))
+		return -1;
+	    tp->tv_sec = tv.tv_sec;
+	    tp->tv_nsec = tv.tv_usec * 1000;
+	    return 0;
+	}
+
+#ifdef __APPLE__
+    case CLOCK_MONOTONIC:
+	{
+	    mach_timespec_t mts;
+	    static clock_serv_t sclock = 0;
+
+	    /*
+	     * Obtain clock port on first call, then reuse it.
+	     * Rely on exit cleanup to free it.
+	     */
+	    if (!sclock) {
+		mach_port_t mach_host = mach_host_self();
+		host_get_clock_service(mach_host,
+		    SYSTEM_CLOCK, &sclock);
+		mach_port_deallocate(mach_task_self(), mach_host);
+	    }
+	    clock_get_time(sclock, &mts);
+	    tp->tv_sec = mts.tv_sec;
+	    tp->tv_nsec = mts.tv_nsec;
+	    return 0;
+	}
+
+    case CLOCK_MONOTONIC_RAW:
+	{
+	    static mach_timebase_info_data_t sTimebaseInfo = {0, 0};
+	    unsigned long long nanos;
+
+	    /* Obtain scale factors on first call, then reuse them. */
+	    if ( sTimebaseInfo.denom == 0 ) {
+		    (void) mach_timebase_info(&sTimebaseInfo);
+	    }
+	    nanos = mach_absolute_time()
+		    * sTimebaseInfo.numer / sTimebaseInfo.denom;
+	    tp->tv_sec = nanos / 1000000000U;
+	    tp->tv_nsec = nanos - tp->tv_sec * 1000000000U;
+	    return 0;
+	}
+#endif /* __APPLE__ */
+
+    default:
+	errno = EINVAL;
+	return -1;
+    }
+}
+
+static inline int clock_getres(clockid_t clk_id, struct timespec *res)
+{
+    switch (clk_id) {
+
+    case CLOCK_REALTIME:
+	res->tv_sec = 0;
+	res->tv_nsec = 1000;
+	return 0;
+
+#ifdef __APPLE__
+    case CLOCK_MONOTONIC:
+    case CLOCK_MONOTONIC_RAW:
+	res->tv_sec = 0;
+	res->tv_nsec = 1;
+	return 0;
+#endif /* __APPLE__ */
+
+    default:
+	errno = EINVAL;
+	return -1;
+    }
+}
+
+/*
+ * Prototype for settimeofday() may suppressed by feature-test flags.
+ * Provide it here just in case, and get an error if it mismatches.
+ * Similarly, "struct timezone" definition may be suppressed, but the
+ * incomplete definition provided here is adequate given that the
+ * timezone argument is unused.
+ */
+struct timezone;
+int settimeofday(const struct timeval *, const struct timezone *);
+
+static inline int clock_settime(clockid_t clk_id, const struct timespec *tp)
+{
+    switch (clk_id) {
+
+    case CLOCK_REALTIME:
+	{
+	    struct timeval tv;
+
+	    tv.tv_sec = tp->tv_sec;
+	    tv.tv_usec = (tp->tv_nsec + 500) / 1000;
+	    return settimeofday(&tv, NULL);
+	}
+
+    default:
+	errno = EINVAL;
+	return -1;
+    }
+}
+
+#endif /* !CLOCK_REALTIME */
 
 int ntp_set_tod (struct timespec *tvs);
 
--- include/ntp_stdlib.h.orig	2023-12-28 20:53:56.000000000 -0800
+++ include/ntp_stdlib.h	2023-12-30 22:12:39.000000000 -0800
@@ -103,7 +103,9 @@ extern	const char * eventstr	(int);
 extern	const char * ceventstr	(int);
 extern	const char * res_match_flags(unsigned short);
 extern	const char * res_access_flags(unsigned short);
+#ifdef HAVE_KERNEL_PLL
 extern	const char * k_st_flags	(uint32_t);
+#endif
 extern	char *	statustoa	(int, int);
 extern	const char * socktoa	(const sockaddr_u *);
 extern	const char * socktoa_r	(const sockaddr_u *sock, char *buf, size_t buflen);
--- include/ntp_syscall.h.orig	2022-12-22 22:08:52.000000000 -0800
+++ include/ntp_syscall.h	2023-12-30 22:12:39.000000000 -0800
@@ -9,9 +9,11 @@
 #ifndef GUARD_NTP_SYSCALL_H
 #define GUARD_NTP_SYSCALL_H
 
+#ifdef HAVE_SYS_TIMEX_H
 # include <sys/time.h>	/* prerequisite on NetBSD */
 # include <sys/timex.h>
 extern int ntp_adjtime_ns(struct timex *);
+#endif
 
 /*
  * The units of the maxerror and esterror fields vary by platform.  If
--- libntp/clockwork.c.orig	2023-12-28 20:53:56.000000000 -0800
+++ libntp/clockwork.c	2023-12-30 22:12:39.000000000 -0800
@@ -5,8 +5,10 @@
 #include "config.h"
 
 #include <unistd.h>
-#include <sys/time.h>	/* prerequisite on NetBSD */
-#include <sys/timex.h>
+#ifdef HAVE_SYS_TIMEX_H
+# include <sys/time.h>	/* prerequisite on NetBSD */
+# include <sys/timex.h>
+#endif
 
 #include "ntp.h"
 #include "ntp_machine.h"
--- libntp/statestr.c.orig	2022-12-22 22:08:52.000000000 -0800
+++ libntp/statestr.c	2023-12-30 22:12:39.000000000 -0800
@@ -12,7 +12,9 @@
 #include "lib_strbuf.h"
 #include "ntp_refclock.h"
 #include "ntp_control.h"
+#ifdef HAVE_KERNEL_PLL
 # include "ntp_syscall.h"
+#endif
 
 
 /*
@@ -186,23 +188,50 @@ static const struct codestring res_acces
 	/* not used with getcode(), no terminating entry needed */
 };
 
+#ifdef HAVE_KERNEL_PLL
 /*
  * kernel discipline status bits
  */
 static const struct codestring k_st_bits[] = {
+# ifdef STA_PLL
 	{ STA_PLL,			"pll" },
+# endif
+# ifdef STA_PPSFREQ
 	{ STA_PPSFREQ,			"ppsfreq" },
+# endif
+# ifdef STA_PPSTIME
 	{ STA_PPSTIME,			"ppstime" },
+# endif
+# ifdef STA_FLL
 	{ STA_FLL,			"fll" },
+# endif
+# ifdef STA_INS
 	{ STA_INS,			"ins" },
+# endif
+# ifdef STA_DEL
 	{ STA_DEL,			"del" },
+# endif
+# ifdef STA_UNSYNC
 	{ STA_UNSYNC,			"unsync" },
+# endif
+# ifdef STA_FREQHOLD
 	{ STA_FREQHOLD,			"freqhold" },
+# endif
+# ifdef STA_PPSSIGNAL
 	{ STA_PPSSIGNAL,		"ppssignal" },
+# endif
+# ifdef STA_PPSJITTER
 	{ STA_PPSJITTER,		"ppsjitter" },
+# endif
+# ifdef STA_PPSWANDER
 	{ STA_PPSWANDER,		"ppswander" },
+# endif
+# ifdef STA_PPSERROR
 	{ STA_PPSERROR,			"ppserror" },
+# endif
+# ifdef STA_CLOCKERR
 	{ STA_CLOCKERR,			"clockerr" },
+# endif
 # ifdef STA_NANO
 	{ STA_NANO,			"nano" },
 # endif
@@ -214,6 +243,7 @@ static const struct codestring k_st_bits
 # endif
 	/* not used with getcode(), no terminating entry needed */
 };
+#endif	/* HAVE_KERNEL_PLL */
 
 /* Forwards */
 static const char *	getcode(int, const struct codestring *);
@@ -318,10 +348,12 @@ decode_bitflags(
 		 "decode_bitflags(%s) can't decode 0x%x in %d bytes",
 		 (tab == peer_st_bits)
 		     ? "peer_st"
-		     :
+		     : 
+#ifdef HAVE_KERNEL_PLL
 		       (tab == k_st_bits)
 			   ? "kern_st"
 			   :
+#endif
 			     "",
 		 (unsigned)bits, (int)LIB_BUFLENGTH);
 	errno = saved_errno;
@@ -360,6 +392,7 @@ res_access_flags(
 }
 
 
+#ifdef HAVE_KERNEL_PLL
 const char *
 k_st_flags(
 	uint32_t st
@@ -367,6 +400,8 @@ k_st_flags(
 {
 	return decode_bitflags((int)st, " ", k_st_bits, COUNTOF(k_st_bits));
 }
+#endif	/* HAVE_KERNEL_PLL */
+
 
 /*
  * statustoa - return a descriptive string for a peer status
--- ntpd/ntp_control.c.orig	2023-12-28 20:53:56.000000000 -0800
+++ ntpd/ntp_control.c	2023-12-30 22:12:39.000000000 -0800
@@ -35,7 +35,9 @@ struct utsname utsnamebuf;
 
 /* Variables that need updating each time. */
 static leap_signature_t lsig;
+#ifdef HAVE_KERNEL_PLL
 static struct timex ntx;
+#endif	/* HAVE_KERNEL_PLL */
 
 /*
  * Statistic counters to keep track of requests and responses.
@@ -364,6 +366,7 @@ static const struct var sys_var[] = {
   Var_uli("authcmacdecrypts", RO, authcmacdecrypt),
   Var_uli("authcmacfails", RO, authcmacfail),
 
+#ifdef HAVE_KERNEL_PLL
 /* kerninfo: Kernel timekeeping info */
   Var_kli("koffset", RO|N_CLOCK|KNUToMS, ntx.offset),
   Var_kli("kfreq", RO|N_CLOCK|K_16, ntx.freq),
@@ -381,6 +384,7 @@ static const struct var sys_var[] = {
   Var_li("kppscaliberrs", RO|N_CLOCK, ntx.errcnt),
   Var_li("kppsjitexc", RO|N_CLOCK, ntx.jitcnt),
   Var_li("kppsstbexc", RO|N_CLOCK, ntx.stbcnt),
+#endif	/* HAVE_KERNEL_PLL */
 
 
 /* refclock stuff in ntp_io */
@@ -1395,7 +1399,9 @@ ctl_putarray(
  */
 static void
 ctl_putsys(const struct var * v) {
+#ifdef HAVE_KERNEL_PLL
 	static unsigned long ntp_adjtime_time;
+#endif	/* HAVE_KERNEL_PLL */
 	static unsigned long ntp_leap_time;
 
 /* older compilers don't allow declarations on each case without {} */
@@ -1407,6 +1413,7 @@ ctl_putsys(const struct var * v) {
  * This should get pushed up a layer: flag, once per request
  * This could get data from 2 samples if the clock ticks while we are working..
  */
+#ifdef HAVE_KERNEL_PLL
 	/* The Kernel clock variables need up-to-date output of ntp_adjtime() */
 	if (v->flags&N_CLOCK && current_time != ntp_adjtime_time) {
 		ZERO(ntx);
@@ -1415,6 +1422,7 @@ ctl_putsys(const struct var * v) {
                             "MODE6: ntp_adjtime() for mode 6 query failed: %s", strerror(errno));
                 ntp_adjtime_time = current_time;
 	}
+#endif	/* HAVE_KERNEL_PLL */
 
 	/* The leap second variables need up-to-date info */
         if (v->flags&N_LEAP && current_time != ntp_leap_time) {
--- ntpd/ntp_loopfilter.c.orig	2023-12-28 20:53:56.000000000 -0800
+++ ntpd/ntp_loopfilter.c	2023-12-30 22:12:39.000000000 -0800
@@ -23,8 +23,10 @@
 
 #define NTP_MAXFREQ	500e-6
 
+#ifdef HAVE_KERNEL_PLL
 # define FREQTOD(x)	((x) / 65536e6)            /* NTP to double */
 # define DTOFREQ(x)	((int32_t)((x) * 65536e6)) /* double to NTP */
+#endif /* HAVE_KERNEL_PLL */
 
 /*
  * This is an implementation of the clock discipline algorithm described
@@ -125,6 +127,7 @@ static void rstclock (int, double); /* t
 static double direct_freq(double); /* direct set frequency */
 static void set_freq(double);	/* set frequency */
 
+#ifdef HAVE_KERNEL_PLL
 #ifndef PATH_MAX
 # define PATH_MAX MAX_PATH
 #endif
@@ -138,6 +141,7 @@ static unsigned int loop_tai;	/* last TA
 #endif /* STA_NANO */
 static	void	start_kern_loop(void);
 static	void	stop_kern_loop(void);
+#endif /* HAVE_KERNEL_PLL */
 
 /*
  * Clock state machine control flags
@@ -154,7 +158,9 @@ struct clock_control_flags clock_ctl = {
 int	freq_cnt;		/* initial frequency clamp */
 
 static int freq_set;		/* initial set frequency switch */
+#ifdef HAVE_KERNEL_PLL
 static bool	ext_enable;	/* external clock enabled */
+#endif /* HAVE_KERNEL_PLL */
 
 /*
  * Clock state machine variables
@@ -172,10 +178,13 @@ static int sys_hufflen;		/* huff-n'-puff
 static int sys_huffptr;		/* huff-n'-puff filter pointer */
 static double sys_mindly;	/* huff-n'-puff filter min delay */
 
+#if defined(HAVE_KERNEL_PLL)
 /* Emacs cc-mode goes nuts if we split the next line... */
 #define MOD_BITS (MOD_OFFSET | MOD_MAXERROR | MOD_ESTERROR | \
     MOD_STATUS | MOD_TIMECONST)
+#endif /* HAVE_KERNEL_PLL */
 
+#ifdef HAVE_KERNEL_PLL
 static void
 sync_status(const char *what, int ostatus, int nstatus) {
 	/* only used in non-lockclock case */
@@ -199,6 +208,7 @@ static char *file_name(void) {
 	}
 	return this_file;
 }
+#endif /* HAVE_KERNEL_PLL */
 
 /*
  * init_loopfilter - initialize loop filter data
@@ -213,6 +223,7 @@ init_loopfilter(void) {
 	freq_cnt = (int)clock_minstep;
 }
 
+#ifdef HAVE_KERNEL_PLL
 /*
  * ntp_adjtime_error_handler - process errors from ntp_adjtime
  */
@@ -411,6 +422,7 @@ or, from ntp_adjtime():
 	}
 	return;
 }
+#endif /* HAVE_KERNEL_PLL */
 
 /*
  * local_clock - the NTP logical clock loop filter.
@@ -444,7 +456,9 @@ local_clock(
 
 	int	rval;		/* return code */
 	int	osys_poll;	/* old system poll */
+#ifdef HAVE_KERNEL_PLL
 	int	ntp_adj_ret;	/* returned by ntp_adjtime */
+#endif /* HAVE_KERNEL_PLL */
 	double	mu;		/* interval since last update */
 	double	clock_frequency; /* clock frequency */
 	double	dtemp, etemp;	/* double temps */
@@ -701,6 +715,7 @@ local_clock(
 		}
 	}
 
+#ifdef HAVE_KERNEL_PLL
 	/*
 	 * This code segment works when clock adjustments are made using
 	 * precision time kernel support and the ntp_adjtime() system
@@ -810,6 +825,7 @@ local_clock(
 		}
 #endif /* STA_NANO */
 	}
+#endif /* HAVE_KERNEL_PLL */
 
 	/*
 	 * Clamp the frequency within the tolerance range and calculate
@@ -921,8 +937,10 @@ adj_host_clock(
 	} else if (freq_cnt > 0) {
 		offset_adj = clock_offset / (CLOCK_PLL * ULOGTOD(1));
 		freq_cnt--;
+#ifdef HAVE_KERNEL_PLL
 	} else if (clock_ctl.pll_control && clock_ctl.kern_enable) {
 		offset_adj = 0.;
+#endif /* HAVE_KERNEL_PLL */
 	} else {
 		offset_adj = clock_offset / (CLOCK_PLL * ULOGTOD(clkstate.sys_poll));
 	}
@@ -933,9 +951,11 @@ adj_host_clock(
 	 * set_freq().  Otherwise it is a component of the adj_systime()
 	 * offset.
 	 */
+#ifdef HAVE_KERNEL_PLL
 	if (clock_ctl.pll_control && clock_ctl.kern_enable)
 		freq_adj = 0.;
 	else
+#endif /* HAVE_KERNEL_PLL */
 		freq_adj = loop_data.drift_comp;
 
 	/* Bound absolute value of total adjustment to NTP_MAXFREQ. */
@@ -1024,6 +1044,7 @@ set_freq(
 
 	loop_data.drift_comp = freq;
 	loop_desc = "ntpd";
+#ifdef HAVE_KERNEL_PLL
 	if (clock_ctl.pll_control) {
 		int ntp_adj_ret;
 		ZERO(ntv);
@@ -1036,10 +1057,12 @@ set_freq(
 		    ntp_adjtime_error_handler(__func__, &ntv, ntp_adj_ret, errno, false, false, __LINE__ - 1);
 		}
 	}
+#endif /* HAVE_KERNEL_PLL */
 	mprintf_event(EVNT_FSET, NULL, "%s %.6f PPM", loop_desc,
 	    loop_data.drift_comp * US_PER_S);
 }
 
+#ifdef HAVE_KERNEL_PLL
 static void
 start_kern_loop(void)
 {
@@ -1075,8 +1098,10 @@ start_kern_loop(void)
 	  	    "kernel time sync enabled");
 	}
 }
+#endif	/* HAVE_KERNEL_PLL */
 
 
+#ifdef HAVE_KERNEL_PLL
 static void
 stop_kern_loop(void)
 {
@@ -1084,6 +1109,7 @@ stop_kern_loop(void)
 		report_event(EVNT_KERN, NULL,
 		    "kernel time sync disabled");
 }
+#endif	/* HAVE_KERNEL_PLL */
 
 
 /*
@@ -1096,11 +1122,15 @@ select_loop(
 {
 	if (clock_ctl.kern_enable == use_kern_loop)
 		return;
+#ifdef HAVE_KERNEL_PLL
 	if (clock_ctl.pll_control && !use_kern_loop)
 		stop_kern_loop();
+#endif /* HAVE_KERNEL_PLL */
 	clock_ctl.kern_enable = use_kern_loop;
+#ifdef HAVE_KERNEL_PLL
 	if (clock_ctl.pll_control && use_kern_loop)
 		start_kern_loop();
+#endif /* HAVE_KERNEL_PLL */
 	/*
 	 * If this loop selection change occurs after initial startup,
 	 * call set_freq() to switch the frequency compensation to or
@@ -1156,10 +1186,12 @@ loop_config(
 	 * variables. Otherwise, continue leaving no harm behind.
 	 */
 	case LOOP_DRIFTINIT:
+#ifdef HAVE_KERNEL_PLL
 		if (loop_data.lockclock || clock_ctl.mode_ntpdate)
 			break;
 
 		start_kern_loop();
+#endif /* HAVE_KERNEL_PLL */
 
 		/*
 		 * Initialize frequency if given; otherwise, begin frequency
@@ -1178,11 +1210,14 @@ loop_config(
 			rstclock(EVNT_FSET, 0);
 		else
 			rstclock(EVNT_NSET, 0);
+#ifdef HAVE_KERNEL_PLL
 		loop_started = true;
+#endif /* HAVE_KERNEL_PLL */
 		break;
 
 	case LOOP_KERN_CLEAR:
 #if 0		/* XXX: needs more review, and how can we get here? */
+# ifdef HAVE_KERNEL_PLL
 		if (!loop_data.lockclock && (clock_ctl.pll_control && clock_ctl.kern_enable)) {
 			memset((char *)&ntv, 0, sizeof(ntv));
 			ntv.modes = MOD_STATUS;
@@ -1192,6 +1227,7 @@ loop_config(
 				pll_status,
 				ntv.status);
 		   }
+# endif /* HAVE_KERNEL_PLL */
 #endif
 		break;
 
@@ -1272,4 +1308,3 @@ loop_config(
 		    "CONFIG: loop_config: unsupported option %d", item);
 	}
 }
-
--- ntpd/ntp_packetstamp.c.orig	2022-12-22 22:08:52.000000000 -0800
+++ ntpd/ntp_packetstamp.c	2023-12-30 22:12:39.000000000 -0800
@@ -6,6 +6,7 @@
  */
 #include "config.h"
 
+#include <stdint.h>
 #ifdef HAVE_SYS_IOCTL_H
 # include <sys/ioctl.h>
 #endif
@@ -33,6 +34,44 @@
  *
  */
 
+/*
+ * OSX prior to 10.6 defines CMSG_DATA incorrectly in 64-bit builds, due to
+ * bad alignment assumptions.
+ *
+ * In those OS versions we substitute a version of the definition from >=10.6.
+ */
+
+#if defined(__APPLE__) \
+  && (!defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) \
+      || __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1060)
+
+#define	__DARWIN_ALIGNBYTES32 (sizeof(__uint32_t) - 1)
+#define	__DARWIN_ALIGN32(p) \
+	((size_t)((char *)(size_t)(p) \
+	 + __DARWIN_ALIGNBYTES32) &~ __DARWIN_ALIGNBYTES32)
+
+/* given pointer to struct cmsghdr, return pointer to data */
+#undef CMSG_DATA
+#define	CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \
+	__DARWIN_ALIGN32(sizeof(struct cmsghdr)))
+
+#endif /* OSX < 10.6 */
+
+/*
+ * Packet timestamps use the kernel's notion of time_t, which may not match
+ * the userspace version.  We need to accomodate both 32- and 64-bit
+ * versions.
+ */
+
+struct timeval_32 {
+	uint32_t	tv_sec;  /* Unsigned to get past 2038 */
+	int32_t		tv_usec;
+};
+
+struct timeval_64 {
+	int64_t		tv_sec;
+	int32_t		tv_usec;
+};
 
 void
 enable_packetstamps(
@@ -104,10 +143,11 @@ fetch_packetstamp(
 	)
 {
 	struct cmsghdr *	cmsghdr;
+	int			datalen;
 #if defined(SO_TIMESTAMPNS) || defined(SO_TS_CLOCK)
 	struct timespec *	tsp;
 #elif defined(SO_TIMESTAMP)
-	struct timeval *	tvp;
+	struct timeval		tv;
 #endif
 #ifdef ENABLE_FUZZ
 	unsigned long		ticks;
@@ -124,6 +164,7 @@ fetch_packetstamp(
 		exit(2);
 		/* return ts;	** Kludge to use time from select. */
 	}
+	datalen = cmsghdr->cmsg_len - sizeof(*cmsghdr);
 #if defined(SO_TIMESTAMPNS)
 	/* Linux and ?? */
 	if (SCM_TIMESTAMPNS != cmsghdr->cmsg_type) {
@@ -160,16 +201,42 @@ fetch_packetstamp(
 		(long)tsp->tv_sec, tsp->tv_nsec));
 	nts = tspec_stamp_to_lfp(*tsp);
 #elif defined(SO_TIMESTAMP)
-	tvp = (struct timeval *)CMSG_DATA(cmsghdr);
+	switch (datalen) {
+
+	case sizeof(struct timeval_32):
+		{
+		struct timeval_32 *tvp = (struct timeval_32 *)
+						CMSG_DATA(cmsghdr);
+		tv.tv_sec = tvp->tv_sec; tv.tv_usec = tvp->tv_usec;
+		}
+		break;
+
+	case sizeof(struct timeval_64):
+		{
+		struct timeval_64 *tvp = (struct timeval_64 *)
+						CMSG_DATA(cmsghdr);
+		tv.tv_sec = tvp->tv_sec; tv.tv_usec = tvp->tv_usec;
+		}
+		break;
+
+	default:
+		DPRINT(4,
+			("fetch_timestamp: bad timestamp length %d",
+			datalen));
+		msyslog(LOG_ERR,
+			"ERR: fetch_timestamp: bad timestamp length %d",
+			datalen);
+		exit(2);
+	}
 #ifdef ENABLE_FUZZ
 	if (sys_tick > measured_tick && sys_tick > S_PER_NS) {
-	    ticks = (unsigned long) ((tvp->tv_usec * S_PER_NS) / sys_tick);
-	    tvp->tv_usec = (long)(ticks * US_PER_S * sys_tick);
+	    ticks = (unsigned long) ((tv.tv_usec * S_PER_NS) / sys_tick);
+	    tv.tv_usec = (long)(ticks * US_PER_S * sys_tick);
 	}
 #endif
 	DPRINT(4, ("fetch_timestamp: system usec network time stamp: %jd.%06ld\n",
-		(intmax_t)tvp->tv_sec, (long)tvp->tv_usec));
-	nts = tspec_stamp_to_lfp(tval_to_tspec(*tvp));
+		(intmax_t)tv.tv_sec, (long)tv.tv_usec));
+	nts = tspec_stamp_to_lfp(tval_to_tspec(tv));
 #else
 # error "Can't get packet timestamp"
 #endif
--- ntpd/ntp_timer.c.orig	2023-12-28 20:53:56.000000000 -0800
+++ ntpd/ntp_timer.c	2023-12-30 22:12:39.000000000 -0800
@@ -13,7 +13,9 @@
 #include <signal.h>
 #include <unistd.h>
 
+#ifdef HAVE_KERNEL_PLL
 #include "ntp_syscall.h"
+#endif /* HAVE_KERNEL_PLL */
 
 #ifdef HAVE_TIMER_CREATE
 /* TC_ERR represents the timer_create() error return value. */
@@ -373,7 +375,11 @@ check_leapsec(
 
 	leap_result_t lsdata;
 	uint32_t       lsprox;
+#ifdef HAVE_KERNEL_PLL
 	leapsec_electric((clock_ctl.pll_control && clock_ctl.kern_enable) ? electric_on : electric_off);
+#else
+	leapsec_electric(electric_off);
+#endif
 #ifdef ENABLE_LEAP_SMEAR
 	leap_smear.enabled = (leap_smear_intv != 0);
 #endif
--- ntpd/refclock_local.c.orig	2022-12-22 22:08:52.000000000 -0800
+++ ntpd/refclock_local.c	2023-12-30 22:12:39.000000000 -0800
@@ -158,6 +158,7 @@ local_poll(
 	 * If another process is disciplining the system clock, we set
 	 * the leap bits and quality indicators from the kernel.
 	 */
+#ifdef HAVE_KERNEL_PLL
 	if (loop_data.lockclock) {
 		struct timex ntv;
 		memset(&ntv,  0, sizeof ntv);
@@ -188,6 +189,13 @@ local_poll(
 		pp->disp = DISPERSION;
 		pp->jitter = 0;
 	}
+	pp->disp = 0;
+	pp->jitter = 0;
+#else /* !HAVE_KERNEL_PLL */
+	pp->leap = LEAP_NOWARNING;
+	pp->disp = DISPERSION;
+	pp->jitter = 0;
+#endif /* !HAVE_KERNEL_PLL */
 	pp->lastref = pp->lastrec;
 	refclock_receive(peer);
 }
--- ntpfrob/precision.c.orig	2023-12-28 20:53:56.000000000 -0800
+++ ntpfrob/precision.c	2023-12-30 22:12:39.000000000 -0800
@@ -11,6 +11,7 @@
 #include "ntp_types.h"
 #include "ntp_calendar.h"
 #include "ntpfrob.h"
+#include "ntp_machine.h"
 
 #define	DEFAULT_SYS_PRECISION	-99
 
--- tests/libntp/statestr.c.orig	2022-12-22 22:08:52.000000000 -0800
+++ tests/libntp/statestr.c	2023-12-30 22:12:39.000000000 -0800
@@ -4,7 +4,9 @@
 #include "unity.h"
 #include "unity_fixture.h"
 
+#ifdef HAVE_SYS_TIMEX_H
 #include <sys/timex.h>
+#endif
 
 TEST_GROUP(statestr);
 
@@ -29,7 +31,9 @@ TEST(statestr, ResAccessFlags) {
 
 // k_st_flags()
 TEST(statestr, KSTFlags) {
+#ifdef STA_PPSFREQ
 	TEST_ASSERT_EQUAL_STRING("ppsfreq", k_st_flags(STA_PPSFREQ));
+#endif
 }
 
 // statustoa
--- wafhelpers/bin_test.py.orig	2022-12-22 22:08:52.000000000 -0800
+++ wafhelpers/bin_test.py	2023-12-30 22:12:39.000000000 -0800
@@ -103,6 +103,12 @@ def cmd_bin_test(ctx):
     if ctx.env['PYTHON_CURSES']:
         cmd_map_python.update(cmd_map_python_curses)
 
+    # Kludge to remove ntptime if it didn't get built
+    if not ctx.env.HEADER_SYS_TIMEX_H:
+        for cmd in list(cmd_map.keys()):
+            if 'ntptime' in cmd[0]:
+                del cmd_map[cmd]
+
     for cmd in sorted(cmd_map):
         if not run(cmd, cmd_map[cmd] % version):
             fails += 1
--- wafhelpers/options.py.orig	2023-12-28 20:53:56.000000000 -0800
+++ wafhelpers/options.py	2023-12-30 22:12:39.000000000 -0800
@@ -23,6 +23,8 @@ def options_cmd(ctx, config):
                    help="Droproot earlier (breaks SHM and NetBSD).")
     grp.add_option('--enable-seccomp', action='store_true',
                    default=False, help="Enable seccomp (restricts syscalls).")
+    grp.add_option('--disable-kernel-pll', action='store_true',
+                   default=False, help="Disable kernel PLL.")
     grp.add_option('--disable-mdns-registration', action='store_true',
                    default=False, help="Disable MDNS registration.")
     grp.add_option(
--- wscript.orig	2023-12-28 20:53:56.000000000 -0800
+++ wscript	2023-12-30 22:12:39.000000000 -0800
@@ -587,7 +587,7 @@ int main(int argc, char **argv) {
     structures = (
         ("struct if_laddrconf", ["sys/types.h", "net/if6.h"], False),
         ("struct if_laddrreq", ["sys/types.h", "net/if6.h"], False),
-        ("struct timex", ["sys/time.h", "sys/timex.h"], True),
+        ("struct timex", ["sys/time.h", "sys/timex.h"], False),
         ("struct ntptimeval", ["sys/time.h", "sys/timex.h"], False),
     )
     for (s, h, r) in structures:
@@ -812,6 +812,21 @@ int main(int argc, char **argv) {
         ctx.define("ENABLE_FUZZ", 1,
                    comment="Enable fuzzing low bits of time")
 
+    # Does the kernel implement a phase-locked loop for timing?
+    # All modern Unixes (in particular Linux and *BSD) have this.
+    #
+    # The README for the (now deleted) kernel directory says this:
+    # "If the precision-time kernel (KERNEL_PLL define) is
+    # configured, the installation process requires the header
+    # file /usr/include/sys/timex.h for the particular
+    # architecture to be in place."
+    #
+    if ((ctx.get_define("HAVE_SYS_TIMEX_H") and
+            not ctx.options.disable_kernel_pll)):
+        ctx.define("HAVE_KERNEL_PLL", 1,
+                   comment="Whether phase-locked loop for timing "
+                   "exists and is enabled")
+
     # SO_REUSEADDR socket option is needed to open a socket on an
     # interface when the port number is already in use on another
     # interface. Linux needs this, NetBSD does not, status on
