<pre style='margin:0'>
Christopher Nielsen (mascguy) pushed a commit to branch master
in repository macports-legacy-support.

</pre>
<p><a href="https://github.com/macports/macports-legacy-support/commit/40c0d2dc4f7a9270b2af1315ada783ecbd49d929">https://github.com/macports/macports-legacy-support/commit/40c0d2dc4f7a9270b2af1315ada783ecbd49d929</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 40c0d2dc4f7a9270b2af1315ada783ecbd49d929
</span>Author: Fred Wright <fw@fwright.net>
AuthorDate: Mon Mar 3 11:17:51 2025 -0800

<span style='display:block; white-space:pre;color:#404040;'>    Fix packet timestamps under Rosetta.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Rosetta fails to swap the CMSG payload from recvmsg(), resulting
</span><span style='display:block; white-space:pre;color:#404040;'>    in garbled packet timestamps.  This adds the missing swapping.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    TESTED:
</span><span style='display:block; white-space:pre;color:#404040;'>    Passes the new packet test on all platforms, including with Rosetta on
</span><span style='display:block; white-space:pre;color:#404040;'>    10.4-10.6 i386/x86_64.
</span>---
 include/MacportsLegacySupport.h |   3 +
 src/packet.c                    | 139 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 142 insertions(+)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/include/MacportsLegacySupport.h b/include/MacportsLegacySupport.h
</span><span style='display:block; white-space:pre;color:#808080;'>index d745982..6553644 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/include/MacportsLegacySupport.h
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/include/MacportsLegacySupport.h
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -183,6 +183,9 @@
</span> #define __MPLS_SDK_CMSG_DATA_FIX__            (__MPLS_SDK_MAJOR < 1060 \
                                                && __MPLS_SDK_MAJOR >= 1050)
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+/* Byte-swapping failure in CMSG data with Rosetta (any OS with PPC) */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define __MPLS_LIB_CMSG_ROSETTA_FIX__         __MPLS_APPLE_PPC__
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> /* stpncpy */
 #define __MPLS_SDK_SUPPORT_STPNCPY__          (__MPLS_SDK_MAJOR < 1070)
 #define __MPLS_LIB_SUPPORT_STPNCPY__          (__MPLS_TARGET_OSVER < 1070)
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/packet.c b/src/packet.c
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 0000000..ffd3aef
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/packet.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,139 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2025 Frederick H. G. Wright II <fw@fwright.net>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Permission to use, copy, modify, and distribute this software for any
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * purpose with or without fee is hereby granted, provided that the above
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * copyright notice and this permission notice appear in all copies.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* MP support header */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include "MacportsLegacySupport.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#if __MPLS_LIB_CMSG_ROSETTA_FIX__
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * There are at least three known issues related to packet timestamps in
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * OS versions prior to 10.7.  In order of discovery, they are:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *   1) The 10.5 sys/socket.h has a bad definition of CMSG_DATA which
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * inappropriately pads the header length to 16 bytes in 64-bit builds,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * resulting in an incorrect payload address.  This is fixed in our wrapper
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * header.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *   2) In 64-bit builds running on a 32-bit 10.4-10.5 kernel,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * the struct timeval supplied by the kernel is based on a 32-bit time_t,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * while userspace expects a version based on a 64-bit time_t.  This is
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * not currently fixed here, but ntpsec has its own workaround for it.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * A future version might fix this, which would involve recopying the entire
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * CMSG stream to adjust any lengths that need it.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *   3) Although Rosetta correctly byte-swaps the CMSG header, it fails
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * to byte-swap the payload, resulting in garbled timestamps.  That is
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * the issue addressed here.  The fix is only applied when the payload
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * length is as expected, but since issue #2 only applies to 64-bit builds
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * and Rosetta doesn't support ppc64, that's not a problem.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Issue #1 applies to all CMSG types, and is fixed for all types.  It is
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * not known at this time whether issues #2 and/or #3 apply to other CMSG
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * types.  If so, the code could be extended appropriately.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <dlfcn.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stddef.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdlib.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/socket.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/sysctl.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/time.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/types.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include "endian.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define CMSG_DATALEN(cmsg) ((uint8_t *) (cmsg) + (cmsg)->cmsg_len \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                       - (uint8_t *) CMSG_DATA(cmsg))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* sysctl to check whether we're running natively (non-ppc only) */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define SYSCTL_NATIVE "sysctl.proc_native"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* Test whether it's Rosetta */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* -1 no, 1 yes */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+check_rosetta(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  int native;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  size_t native_sz = sizeof(native);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (sysctlbyname(SYSCTL_NATIVE, &native, &native_sz, NULL, 0) < 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* If sysctl failed, must be real ppc. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  return native ? -1 : 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* Fix endianness of CMSG payloads */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static void
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+fix_cmsg_endianness(struct msghdr *msghdr)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   struct cmsghdr *cmsghdr;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   struct timeval *tvp;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  cmsghdr = CMSG_FIRSTHDR(msghdr);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  while (cmsghdr) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (cmsghdr->cmsg_level == SOL_SOCKET) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      switch (cmsghdr->cmsg_type) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      case SCM_TIMESTAMP:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (CMSG_DATALEN(cmsghdr) != sizeof(*tvp)) break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        tvp = (struct timeval *) CMSG_DATA(cmsghdr);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        BYTE_SWAP_INPLACE(tvp->tv_sec);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        BYTE_SWAP_INPLACE(tvp->tv_usec);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ssize_t
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+recvmsg(int socket, struct msghdr *message, int flags)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  static __typeof__(recvmsg) *sys_recvmsg = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  static int is_rosetta = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  ssize_t ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (!sys_recvmsg) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!(sys_recvmsg = dlsym(RTLD_NEXT, "recvmsg"))){
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      /* Something's badly wrong if we can't find the function */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      abort();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  /* Determine Rosettaness, if not already known */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (!is_rosetta) is_rosetta = check_rosetta();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  /* Just pass through if not Rosetta */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (is_rosetta < 0) return (*sys_recvmsg)(socket, message, flags);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  /* Running under Rosetta - need to intercept return */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  ret = (*sys_recvmsg)(socket, message, flags);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  /* If error or no CMSG data, just return */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (ret < 0 || !message->msg_controllen) return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  /* Otherwise, fix the data */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  fix_cmsg_endianness(message);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* __MPLS_LIB_CMSG_ROSETTA_FIX__ */
</span></pre><pre style='margin:0'>

</pre>