Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package nqptp for openSUSE:Factory checked in at 2026-06-04 18:54:56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/nqptp (Old) and /work/SRC/openSUSE:Factory/.nqptp.new.2375 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "nqptp" Thu Jun 4 18:54:56 2026 rev:3 rq:1357027 version:1.2.8 Changes: -------- --- /work/SRC/openSUSE:Factory/nqptp/nqptp.changes 2024-09-05 15:48:26.875211250 +0200 +++ /work/SRC/openSUSE:Factory/.nqptp.new.2375/nqptp.changes 2026-06-04 18:57:04.807723079 +0200 @@ -1,0 +2,19 @@ +Wed Jun 3 18:33:07 UTC 2026 - Martin Pluskal <[email protected]> + +- Update to version 1.2.8: + * The systemd service now runs as a DynamicUser and uses + AmbientCapabilities=CAP_NET_BIND_SERVICE to bind ports + 319/320, so no static user and no setcap on the binary are + needed anymore + * Improved error messages; ship a nqptp(8) man page + * Add FreeBSD and OpenBSD support +- Drop backported patches (merged upstream): + * backport-050a8c2de9f3e1f4859abf9b36d2f18afd4c34d7.patch + * backport-b5321a88d21b854aaa461dc0f6c226d650309b91.patch +- Drop disable-user-group-generation.patch and the nqptp-user.conf + sysusers file: upstream no longer creates a static user (it uses + systemd DynamicUser), so the sysusers handling is obsolete +- The service file is now installed to the proper systemd unit + directory directly, so the manual relocation is dropped + +------------------------------------------------------------------- Old: ---- backport-050a8c2de9f3e1f4859abf9b36d2f18afd4c34d7.patch backport-b5321a88d21b854aaa461dc0f6c226d650309b91.patch disable-user-group-generation.patch nqptp-1.2.4.tar.gz nqptp-user.conf New: ---- nqptp-1.2.8.tar.gz ----------(Old B)---------- Old:- Drop backported patches (merged upstream): * backport-050a8c2de9f3e1f4859abf9b36d2f18afd4c34d7.patch * backport-b5321a88d21b854aaa461dc0f6c226d650309b91.patch Old: * backport-050a8c2de9f3e1f4859abf9b36d2f18afd4c34d7.patch * backport-b5321a88d21b854aaa461dc0f6c226d650309b91.patch - Drop disable-user-group-generation.patch and the nqptp-user.conf Old: * backport-b5321a88d21b854aaa461dc0f6c226d650309b91.patch - Drop disable-user-group-generation.patch and the nqptp-user.conf sysusers file: upstream no longer creates a static user (it uses ----------(Old E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ nqptp.spec ++++++ --- /var/tmp/diff_new_pack.cS4vAJ/_old 2026-06-04 18:57:05.735761410 +0200 +++ /var/tmp/diff_new_pack.cS4vAJ/_new 2026-06-04 18:57:05.735761410 +0200 @@ -1,7 +1,7 @@ # # spec file for package nqptp # -# Copyright (c) 2024 SUSE LLC +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,24 +17,16 @@ Name: nqptp -Version: 1.2.4 +Version: 1.2.8 Release: 0 Summary: Not Quite PTP License: GPL-2.0-only URL: https://github.com/mikebrady/nqptp Source0: https://github.com/mikebrady/%{name}/archive/%{version}/%{name}-%{version}.tar.gz -Source1: nqptp-user.conf -# Backported from 1.2.5-dev: -Patch0: backport-050a8c2de9f3e1f4859abf9b36d2f18afd4c34d7.patch -# Backported from 1.2.5-dev: -Patch1: backport-b5321a88d21b854aaa461dc0f6c226d650309b91.patch -Patch2: disable-user-group-generation.patch BuildRequires: autoconf BuildRequires: automake BuildRequires: systemd-rpm-macros -BuildRequires: sysuser-tools %{?systemd_ordering} -%sysusers_requires %description nqptp is a daemon that monitors timing data from any PTP clocks – up to 64 – it @@ -51,14 +43,9 @@ autoreconf -i -f %configure --with-systemd-startup %make_build -%sysusers_generate_pre %{SOURCE1} nqptp nqptp-user.conf %install %make_install -mkdir -p %{buildroot}%{_unitdir} -mv %{buildroot}%{_libdir}/systemd/system/%{name}.service \ - %{buildroot}%{_unitdir}/%{name}.service -install -D -m 0644 %{SOURCE1} %{buildroot}%{_sysusersdir}/nqptp.conf %pre %service_add_pre %{name}.service @@ -76,6 +63,6 @@ %license LICENSE %doc README.md RELEASE_NOTES.md %{_bindir}/%{name} +%{_mandir}/man8/%{name}.8%{?ext_man} %{_unitdir}/%{name}.service -%{_sysusersdir}/nqptp.conf ++++++ nqptp-1.2.4.tar.gz -> nqptp-1.2.8.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nqptp-1.2.4/.gitignore new/nqptp-1.2.8/.gitignore --- old/nqptp-1.2.4/.gitignore 2023-09-16 19:51:55.000000000 +0200 +++ new/nqptp-1.2.8/.gitignore 2026-05-13 16:33:47.000000000 +0200 @@ -53,6 +53,7 @@ # Executable nqptp -# Version file generated from '$ git describe --dirty' +# Version files generated from check-gitversion gitversion.h +gitversion-stamp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nqptp-1.2.4/Makefile.am new/nqptp-1.2.8/Makefile.am --- old/nqptp-1.2.4/Makefile.am 2023-09-16 19:51:55.000000000 +0200 +++ new/nqptp-1.2.8/Makefile.am 2026-05-13 16:33:47.000000000 +0200 @@ -1,33 +1,30 @@ bin_PROGRAMS = nqptp nqptp_SOURCES = nqptp.c nqptp-clock-sources.c nqptp-message-handlers.c nqptp-utilities.c general-utilities.c debug.c +man_MANS = nqptp.8 AM_CFLAGS = -fno-common -Wall -Wextra -pthread --include=config.h -CLEANFILES = + if USE_GIT_VERSION -nqptp.c: gitversion.h -gitversion.h: .git/index - echo "// Do not edit!" > gitversion.h - echo "// This file is automatically generated by 'git describe --tags --dirty --broken', if available." >> gitversion.h - echo -n " char git_version_string[] = \"" >> gitversion.h - git describe --tags --dirty --broken | tr -d '[[:space:]]' >> gitversion.h - echo "\";" >> gitversion.h -FORCE: ; -CLEANFILES += gitversion.h -endif +## Check if the git version information has changed and rebuild gitversion.h if so +.PHONY: gitversion-check +gitversion-check: + $(top_srcdir)/check-gitversion +BUILT_SOURCES = gitversion-check +CLEANFILES = gitversion-stamp gitversion.h +endif install-exec-hook: if BUILD_FOR_LINUX -# NQPTP runs as user/group nqptp/nqptp on Linux and uses setcap to access ports 319 and 320 - setcap 'cap_net_bind_service=+ep' $(bindir)/nqptp +# Note: 1. NQPTP runs as a dynamic user on systemd-based Linux. +# 2. Access to ports 319 and 320 is given via AmbientCapabilities in the service file. +# If you want to run NQPTP from the command line, e.g. for debugging, run it as root user. # no installer for System V if INSTALL_SYSTEMD_STARTUP - getent group nqptp &>/dev/null || groupadd -r nqptp &>/dev/null - getent passwd nqptp &> /dev/null || useradd -r -M -g nqptp -s /usr/sbin/nologin nqptp &>/dev/null - [ -e $(DESTDIR)$(libdir)/systemd/system ] || mkdir -p $(DESTDIR)$(libdir)/systemd/system + [ -e $(DESTDIR)$(systemdsystemunitdir) ] || mkdir -p $(DESTDIR)$(systemdsystemunitdir) # don't replace a service file if it already exists... - [ -e $(DESTDIR)$(libdir)/systemd/system/nqptp.service ] || cp nqptp.service $(DESTDIR)$(libdir)/systemd/system + [ -e $(DESTDIR)$(systemdsystemunitdir)/nqptp.service ] || cp nqptp.service $(DESTDIR)$(systemdsystemunitdir) endif endif @@ -39,4 +36,7 @@ endif endif - +if BUILD_FOR_OPENBSD +# NQPTP starts as root on OpenBSD to access ports 319 and 320 +# and drops privileges to the user shairport is running as. +endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nqptp-1.2.4/README.md new/nqptp-1.2.8/README.md --- old/nqptp-1.2.4/README.md 2023-09-16 19:51:55.000000000 +0200 +++ new/nqptp-1.2.8/README.md 2026-05-13 16:33:47.000000000 +0200 @@ -22,12 +22,13 @@ ``` ### Remove Old Service Files #### Linux -If you are updating from version `1.2.4d0` or earlier in Linux, remove the service file `nqptp.service` from the directory `/lib/systemd/system` (you'll need superuser privileges): +If you are updating from version `1.2.4` or earlier in Linux, remove the service file `nqptp.service` from the directories `/lib/systemd/system` and `/usr/local/lib/systemd/system` (you'll need superuser privileges): ``` # rm /lib/systemd/system/nqptp.service +# rm /usr/local/lib/systemd/system/nqptp.service # systemctl daemon-reload ``` -Don't worry if you get a message stating that the file doesn't exist -- no harm done. +Don't worry if you get a message stating that the files doesn't exist -- no harm done. #### FreeBSD At present, there is no need to remove the old startup script as (in FreeBSD only) it is always replaced during the `# make install` step. @@ -42,6 +43,7 @@ ``` $ git clone https://github.com/mikebrady/nqptp.git $ cd nqptp +$ autoreconf -fi # about a minute on a Raspberry Pi. $ ./configure --with-systemd-startup $ make # make install @@ -108,7 +110,7 @@ ## Notes The `nqptp` application requires exclusive access to ports 319 and 320. This means that it can not coexist with any other user of those ports, such as full PTP service daemons. -In Linux, `nqptp` runs as a low-priviliged user but is given special access to ports 319 and 320 during installation using the `setcap` utility. +In Linux, `nqptp` runs as a low-priviliged user but is given special access to ports 319 and 320 using systemd `AmbientCapabilities`. In FreeBSD, `nqptp` runs as `root` user. ## Programming Notes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nqptp-1.2.4/RELEASE_NOTES.md new/nqptp-1.2.8/RELEASE_NOTES.md --- old/nqptp-1.2.4/RELEASE_NOTES.md 2023-09-16 19:51:55.000000000 +0200 +++ new/nqptp-1.2.8/RELEASE_NOTES.md 2026-05-13 16:33:47.000000000 +0200 @@ -1,10 +1,59 @@ +## Version 1.2.8 +* A new `man` file. Thanks again to [Chris Boot](https://github.com/bootc) for the [PR](https://github.com/mikebrady/nqptp/pull/48). + +## Version 1.2.7 +* With this update, `pkg-config` is used to determine the correct location for `systemdsystemunitdir`. +* Additionally, `--with-systemdsystemunitdir` `./configure...` option is added to allow the location to be over-ridden. + +**Note** If you are updating an existing installation, you'll need to delete the existing service file as directed in the [README](https://github.com/mikebrady/nqptp/blob/main/README.md#remove-old-service-files). + +Thanks to [Chris Boot](https://github.com/bootc) for the [PR](https://github.com/mikebrady/nqptp/pull/46). + +## Version 1.2.6 +* This update should make synchronisation a little better and a little smoother. + + **Note** If you are updating an existing installation, you'll need to delete the existing service file as directed in the [README](https://github.com/mikebrady/nqptp/blob/main/README.md#remove-old-service-files). You must also redo the `./configure --with-systemd-startup` step to generate the updated `systemd` service file. + +## Version: 1.2.5-dev-29-ga93ba70 +* Use a new method to get versioning information from `git describe`. It recognises when a repository gets 'dirty' immediately. + +## Version: 1.2.5-dev-27-gb59628b +* Use Linux scheduling to give NQPTP slightly increased priority. This should make it more likely that NQPTP will be able to accurately time the arrival of timing packets and thus make synchronisation a little smoother. At startup, NQPTP will request FIFO scheduling and an associated priority. If it's not available, it will just carry on as before. The `systemd` service file has been updated to grant NQPTP limited permission to set scheduling and priority. + +## Version: 1.2.5-dev-24-g494ff3f +* Following a [suggestion](https://github.com/mikebrady/nqptp/issues/33) by [Jörn Nettingsmeier](https://github.com/nettings), use the `DynamicUser` facility provided by `systemd` to define the system user needed to run the NQPTP daemon. Many thanks to them. New installations will use this arrangement. + Optionally, if you wish to use it on an existing installation: + ``` + # rm /usr/local/lib/systemd/system/nqptp.service + # systemctl daemon-reload + ``` + before building and installing NQPTP. + +## Version: 1.2.5-dev-18-gb8384c4 +* Documentation fix. Thanks to [Rudi Heitbaum](https://github.com/heitbaum) for a documentation fix in [PR 34](https://github.com/mikebrady/nqptp/pull/34). +## Version: 1.2.5-dev-16-g32bfe78 +* OpenBSD compatibility, thanks to the work of [Klemens Nanni](https://github.com/klemensn) in [PR 31](https://github.com/mikebrady/nqptp/pull/31). This work includes: using OpenBSD's `pledge(2)` facilities to harden the security of NQPTP, dropping priviliges as soon as possible, and running as the same user as the Shairport Sync application. (Note that at present on Linux, NQPTP runs as the user `nqptp` while Shairport Sync runs as the user `shairport-sync`. For consistency, this may change in future.) +## Version: 1.2.5-dev-5-g475d7a1 +* Fixup for FreeBSD compilation error -- change the order of some of the `#include` files. +## Version: 1.2.5-dev-2-gb5321a8 +* Stop using `setcap` on the `nqptp` binary at install time and instead use systemd's AmbientCapabilities to give the `nqptp` daemon the capability to access ports 319 and 320. Many thanks to [Hs_Yeah](https://github.com/Hs-Yeah) for the [PR](https://github.com/mikebrady/nqptp/pull/26). +* Improve some error messages. +* Update a few documentation errors. +* Fix some compilation errors on FreeBSD. Thanks to [Emanuel Haupt](https://github.com/ehaupt) who also discovered these errors and proposed a fix. + +When updating NQPTP on Linux, be sure to remove old service files as directed in the [README](https://github.com/mikebrady/nqptp/blob/main/README.md#remove-old-service-files). +Note: Shairport Sync must be using Shared Memory Interface Version: `smi10`. Check by running: +``` +$ shairport-sync -V +``` + ## Version: 1.2.4 This is an important security update. The Shared Memory Interface of the updated NQPTP is now 10, i.e. `smi10`: ``` $ nqptp -V Version: 1.2.4. Shared Memory Interface Version: smi10. ``` -1. When updating NQPTP on Linux, be sure to remove the old service file as directed in the [README](https://github.com/mikebrady/nqptp/blob/main/README.md#remove-old-service-files). +1. When updating NQPTP on Linux, be sure to remove old service files as directed in the [README](https://github.com/mikebrady/nqptp/blob/main/README.md#remove-old-service-files). 2. You must update Shairport Sync to ensure that it's Shared Memory Interface version is also 10 in order to be compatible with this NQPTP update. 3. Having completed both updates and installations, remember to restart NQPTP first and then restart Shairport Sync. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nqptp-1.2.4/check-gitversion new/nqptp-1.2.8/check-gitversion --- old/nqptp-1.2.4/check-gitversion 1970-01-01 01:00:00.000000000 +0100 +++ new/nqptp-1.2.8/check-gitversion 2026-05-13 16:33:47.000000000 +0200 @@ -0,0 +1,37 @@ +#! /bin/sh +# echo "This is the git version checker" +test -f gitversion-stamp && BGD=`cat gitversion-stamp` || : +# echo "existing gitversion-stamp is $BGD" +GD=`git describe --tags --dirty --broken --always 2>/dev/null` +if [ x"$GD" = x ] ; then + GD="NA" +fi +# echo "current git description is $GD" +if [ x"$GD" != x"$BGD" ] ; then + echo "build: $GD" # optional -- displays git version if new or different + echo $GD > gitversion-stamp + echo "// Do not edit!" > gitversion.h + echo "// This file is automatically generated." >> gitversion.h + echo -n " char git_version_string[] = \"" >> gitversion.h + ## the tr is because we need to remove the trailing newline + cat gitversion-stamp | tr -d '[[:space:]]' >> gitversion.h + echo "\";" >> gitversion.h +fi + +# Usage. Below is what you would add to Makefile.am. When it runs, the +# following two files are generated: 'gitversion-stamp' and 'gitversion.h'. + +# gitversion-stamp stores the most recently used git description. +# gitversion.h is a C header file containing that git description as a string. + +# Put this script in the top level source folder and make sure it has execute permission. + +# These are the lines (remove the leading '#' on each) to add to the Makefile.am file: +# ## Check if the git version information has changed and rebuild gitversion.h if so. +# .PHONY: gitversion-check +# gitversion-check: +# $(top_srcdir)/check-gitversion + +# ## You may have to change from += to = below: +# BUILT_SOURCES += gitversion-check +# CLEANFILES += gitversion-stamp gitversion.h diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nqptp-1.2.4/configure.ac new/nqptp-1.2.8/configure.ac --- old/nqptp-1.2.4/configure.ac 2023-09-16 19:51:55.000000000 +0200 +++ new/nqptp-1.2.8/configure.ac 2026-05-13 16:33:47.000000000 +0200 @@ -2,12 +2,15 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.68]) -AC_INIT([nqptp], [1.2.4], [[email protected]]) +AC_INIT([nqptp], [1.2.8], [[email protected]]) +: ${CFLAGS="-O3"} +: ${CXXFLAGS="-O3"} AM_INIT_AUTOMAKE AC_CANONICAL_HOST build_linux=no build_freebsd=no +build_openbsd=no # Detect the target system case "${host_os}" in @@ -16,7 +19,10 @@ ;; freebsd*) build_freebsd=yes - ;; + ;; + openbsd*) + build_openbsd=yes + ;; *) AC_MSG_ERROR(["OS $host_os is not supported"]) ;; @@ -25,6 +31,7 @@ # Pass the conditionals to automake AM_CONDITIONAL([BUILD_FOR_LINUX], [test "$build_linux" = "yes"]) AM_CONDITIONAL([BUILD_FOR_FREEBSD], [test "$build_freebsd" = "yes"]) +AM_CONDITIONAL([BUILD_FOR_OPENBSD], [test "$build_openbsd" = "yes"]) if test "x$build_linux" = "xyes" ; then AC_DEFINE([CONFIG_FOR_LINUX], 1, [Build for Linux.]) @@ -32,6 +39,9 @@ if test "x$build_freebsd" = "xyes" ; then AC_DEFINE([CONFIG_FOR_FREEBSD], 1, [Build for FreeBSD.]) fi +if test "x$build_openbsd" = "xyes" ; then + AC_DEFINE([CONFIG_FOR_OPENBSD], 1, [Build for OpenBSD.]) +fi AC_CHECK_PROGS([GIT], [git]) if test -n "$GIT" && test -e ".git/index" ; then @@ -44,10 +54,16 @@ AC_ARG_WITH([systemd-startup],[AS_HELP_STRING([--with-systemd-startup],[install a systemd startup script during a make install])]) AM_CONDITIONAL([INSTALL_SYSTEMD_STARTUP], [test "x$with_systemd_startup" = "xyes"]) -# Check to see if we should include the systemd stuff to define it as a service +# Check to see if we should include the FreeBSD stuff to define it as a service AC_ARG_WITH([freebsd-startup],[AS_HELP_STRING([--with-freebsd-startup],[install a FreeBSD startup script during a make install])]) AM_CONDITIONAL([INSTALL_FREEBSD_STARTUP], [test "x$with_freebsd_startup" = "xyes"]) +# Determins where to install the systemd unit when requested +AC_ARG_WITH([systemdsystemunitdir], + [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], + [Directory for systemd service files @<:@auto@:>@])], + [with_systemdsystemunitdir=$withval], + [with_systemdsystemunitdir=auto]) AC_CONFIG_SRCDIR([nqptp.c]) AC_CONFIG_HEADERS([config.h]) @@ -55,10 +71,14 @@ # Checks for programs. AC_PROG_CC AC_PROG_INSTALL +PKG_PROG_PKG_CONFIG # Checks for libraries. AC_CHECK_LIB([pthread],[pthread_create], , AC_MSG_ERROR(pthread library needed)) -AC_CHECK_LIB([rt],[clock_gettime], , AC_MSG_ERROR(librt needed for shared memory library)) +if test "x$build_openbsd" = "xno" ; then + # part of libc + AC_CHECK_LIB([rt],[clock_gettime], , AC_MSG_ERROR(librt needed for shared memory library)) +fi # Checks for header files. AC_CHECK_HEADERS([arpa/inet.h inttypes.h netdb.h stdlib.h string.h sys/socket.h unistd.h]) @@ -71,5 +91,19 @@ AC_FUNC_MALLOC AC_CHECK_FUNCS([clock_gettime inet_ntoa memset select socket strerror]) +# Configure the systemd unit location +AS_IF([test "x$with_systemdsystemunitdir" = "xauto"], + [AS_IF([test "x$PKG_CONFIG" != "x"], + [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd 2>/dev/null)], + [with_systemdsystemunitdir=]) + AS_IF([test "x$with_systemdsystemunitdir" = "x"], + [with_systemdsystemunitdir='${prefix}/lib/systemd/system'])]) + +AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir]) + +AS_IF([test "x$with_systemd_startup" = "xyes"], + [AC_MSG_NOTICE([systemd unit directory: $with_systemdsystemunitdir])]) + + AC_CONFIG_FILES([Makefile nqptp.service]) AC_OUTPUT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nqptp-1.2.4/debug.c new/nqptp-1.2.8/debug.c --- old/nqptp-1.2.4/debug.c 2023-09-16 19:51:55.000000000 +0200 +++ new/nqptp-1.2.8/debug.c 2026-05-13 16:33:47.000000000 +0200 @@ -59,6 +59,10 @@ debugger_show_file_and_line = show_file_and_line; } +int debug_level() { + return debuglev; +} + char *generate_preliminary_string(char *buffer, size_t buffer_length, double tss, double tsl, const char *filename, const int linenumber, const char *prefix) { size_t space_remaining = buffer_length; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nqptp-1.2.4/debug.h new/nqptp-1.2.8/debug.h --- old/nqptp-1.2.4/debug.h 2023-09-16 19:51:55.000000000 +0200 +++ new/nqptp-1.2.8/debug.h 2026-05-13 16:33:47.000000000 +0200 @@ -22,6 +22,7 @@ // level 0 is no messages, level 3 is most messages void debug_init(int level, int show_elapsed_time, int show_relative_time, int show_file_and_line); +int debug_level(); // get current debug level void _die(const char *filename, const int linenumber, const char *format, ...); void _warn(const char *filename, const int linenumber, const char *format, ...); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nqptp-1.2.4/nqptp-utilities.c new/nqptp-1.2.8/nqptp-utilities.c --- old/nqptp-1.2.4/nqptp-utilities.c 2023-09-16 19:51:55.000000000 +0200 +++ new/nqptp-1.2.8/nqptp-utilities.c 2026-05-13 16:33:47.000000000 +0200 @@ -28,12 +28,12 @@ #include <linux/if_packet.h> // sockaddr_ll #endif -#ifdef CONFIG_FOR_FREEBSD +#if defined(CONFIG_FOR_FREEBSD) || defined(CONFIG_FOR_OPENBSD) +#include <sys/types.h> +#include <unistd.h> #include <net/if_dl.h> #include <net/if_types.h> #include <sys/socket.h> -#include <sys/types.h> -#include <unistd.h> #endif #include <netdb.h> // getaddrinfo etc. @@ -105,65 +105,63 @@ } freeaddrinfo(info); if (sockets_opened == 0) { - if (port < 1024) - die("unable to listen on port %d. The error is: \"%s\". NQPTP must run as root to access " - "this port. Or is another PTP daemon -- possibly another instance on NQPTP -- running " - "already?", - port, strerror(errno)); - else - die("unable to listen on port %d. The error is: \"%s\". " - "Is another instance on NQPTP running already?", - port, strerror(errno)); + if (errno == EACCES) { + die("nqptp does not have permission to access port %u. It must (a) [Linux only] have been given CAP_NET_BIND_SERVICE capabilities using e.g. setcap or systemd's AmbientCapabilities, or (b) start as root.", port); + } else { + die("nqptp is unable to listen on port %u. The error is: %d, \"%s\".", port, errno, strerror(errno)); + } } } void debug_print_buffer(int level, char *buf, size_t buf_len) { - // printf("Received %u bytes in a packet from %s:%d\n", buf_len, inet_ntoa(si_other.sin_addr), - // ntohs(si_other.sin_port)); - char *obf = - malloc(buf_len * 4 + 1); // to be on the safe side -- 4 characters on average for each byte - if (obf != NULL) { - char *obfp = obf; - unsigned int obfc; - for (obfc = 0; obfc < buf_len; obfc++) { - snprintf(obfp, 3, "%02X", buf[obfc]); - obfp += 2; - if (obfc != buf_len - 1) { - if (obfc % 32 == 31) { - snprintf(obfp, 5, " || "); - obfp += 4; - } else if (obfc % 16 == 15) { - snprintf(obfp, 4, " | "); - obfp += 3; - } else if (obfc % 4 == 3) { - snprintf(obfp, 2, " "); - obfp += 1; + if (debug_level() >= level) { + // printf("Received %u bytes in a packet from %s:%d\n", buf_len, inet_ntoa(si_other.sin_addr), + // ntohs(si_other.sin_port)); + char *obf = + malloc(buf_len * 4 + 1); // to be on the safe side -- 4 characters on average for each byte + if (obf != NULL) { + char *obfp = obf; + unsigned int obfc; + for (obfc = 0; obfc < buf_len; obfc++) { + snprintf(obfp, 3, "%02X", buf[obfc]); + obfp += 2; + if (obfc != buf_len - 1) { + if (obfc % 32 == 31) { + snprintf(obfp, 5, " || "); + obfp += 4; + } else if (obfc % 16 == 15) { + snprintf(obfp, 4, " | "); + obfp += 3; + } else if (obfc % 4 == 3) { + snprintf(obfp, 2, " "); + obfp += 1; + } } + }; + *obfp = 0; + switch (buf[0]) { + + case 0x10: + debug(level, "SYNC: \"%s\".", obf); + break; + case 0x18: + debug(level, "FLUP: \"%s\".", obf); + break; + case 0x19: + debug(level, "DRSP: \"%s\".", obf); + break; + case 0x1B: + debug(level, "ANNC: \"%s\".", obf); + break; + case 0x1C: + debug(level, "SGNL: \"%s\".", obf); + break; + default: + debug(1, "XXXX \"%s\".", obf); // output this at level 1 + break; } - }; - *obfp = 0; - switch (buf[0]) { - - case 0x10: - debug(level, "SYNC: \"%s\".", obf); - break; - case 0x18: - debug(level, "FLUP: \"%s\".", obf); - break; - case 0x19: - debug(level, "DRSP: \"%s\".", obf); - break; - case 0x1B: - debug(level, "ANNC: \"%s\".", obf); - break; - case 0x1C: - debug(level, "SGNL: \"%s\".", obf); - break; - default: - debug(1, "XXXX \"%s\".", obf); // output this at level 1 - break; + free(obf); } - free(obf); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nqptp-1.2.4/nqptp.8 new/nqptp-1.2.8/nqptp.8 --- old/nqptp-1.2.4/nqptp.8 1970-01-01 01:00:00.000000000 +0100 +++ new/nqptp-1.2.8/nqptp.8 2026-05-13 16:33:47.000000000 +0200 @@ -0,0 +1,89 @@ +.TH NQPTP 8 "May 7, 2026" "nqptp" "System Manager's Manual" +.SH NAME +nqptp \- Not Quite PTP: PTP-based timing daemon for Apple AirPlay 2 +.SH SYNOPSIS +.B nqptp +.RB [ \-V ] +.RB [ \-v | \-vv | \-vvv ] +.RB [ \-h ] +.SH DESCRIPTION +.B nqptp +is a daemon that monitors timing data from PTP (Precision Time Protocol) +clocks. It is designed exclusively as a companion daemon to +.BR shairport-sync (1), +which uses it to obtain the accurate timing information required for +AirPlay 2 audio playback. +.PP +.B nqptp +must be running before +.B shairport-sync +is started with AirPlay 2 support enabled. It communicates with +.B shairport-sync +via a shared memory interface and does not require any configuration +file. +.PP +Under normal operation, +.B nqptp +runs silently in the background. It is typically started at boot time +via a service manager such as +.BR systemd (1). +.SH OPTIONS +.TP +.B \-V +Print the version number and exit. +.TP +.B \-v +Enable verbose logging. Basic informational messages about timing +sources and state changes are written to the system log. +.TP +.B \-vv +Enable more verbose logging. Additional detail about PTP clock +selection and timing computations is included. +.TP +.B \-vvv +Enable very verbose logging. Full diagnostic output, including +low-level PTP message handling. Intended for debugging only. +.TP +.B \-h +Print a brief help summary and exit. +.SH SIGNALS +.TP +.B SIGTERM +Cleanly shut down the daemon, releasing the shared memory interface +before exiting. +.TP +.B SIGINT +Cleanly shut down the daemon, equivalent to +.BR SIGTERM . +.SH FILES +.TP +.I /dev/shm/nqptp +Shared memory segment used to pass timing data to +.BR shairport-sync (1). +.SH NOTES +.B nqptp +listens on UDP port 319 and 320, the standard PTP event and general +message ports. It therefore requires either +.B CAP_NET_BIND_SERVICE +or root privileges in order to bind these ports. When running under +.BR systemd (1), +the provided unit file grants the necessary capability without +requiring the daemon to run as root. +.PP +Only one instance of +.B nqptp +should be run at a time on a given host. +.SH SEE ALSO +.BR shairport-sync (1), +.BR ptp4l (8), +.BR systemd (1) +.SH BUGS +Please report bugs at +.IR https://github.com/mikebrady/nqptp/issues . +.SH AUTHORS +.B nqptp +was written by Mike Brady. +.PP +This man page was originally written for the Debian package of +.BR nqptp +by Chris Boot <[email protected]>. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nqptp-1.2.4/nqptp.c new/nqptp-1.2.8/nqptp.c --- old/nqptp-1.2.4/nqptp.c 2023-09-16 19:51:55.000000000 +0200 +++ new/nqptp-1.2.8/nqptp.c 2026-05-13 16:33:47.000000000 +0200 @@ -48,11 +48,17 @@ #include <netdb.h> #include <sys/socket.h> -#ifdef CONFIG_FOR_FREEBSD +#if defined(CONFIG_FOR_FREEBSD) || defined(CONFIG_FOR_OPENBSD) #include <netinet/in.h> #include <sys/socket.h> #endif +#ifdef CONFIG_FOR_OPENBSD +#include <sys/types.h> +#include <unistd.h> +#include <pwd.h> +#endif + #ifndef FIELD_SIZEOF #define FIELD_SIZEOF(t, f) (sizeof(((t *)0)->f)) #endif @@ -125,6 +131,11 @@ } int main(int argc, char **argv) { +#ifdef CONFIG_FOR_OPENBSD + if (pledge("stdio rpath tmppath inet dns id", NULL) == -1) { + die("pledge: %s", strerror(errno)); + } +#endif int debug_level = 0; int i; @@ -174,9 +185,22 @@ // debug(1, "size of a clock entry is %u bytes.", sizeof(clock_source_private_data)); atexit(goodbye); - + + + // try to set a real time scheduling policy with a priority of -6 + int policy = SCHED_FIFO; + struct sched_param param; + param.sched_priority = 5; + int s = pthread_setschedparam(pthread_self(), policy, ¶m); + if (s != 0) + debug(1, "pthread_setschedparam failed: %d -- \"%s\".", s, strerror(s)); + sockets_open_stuff.sockets_open = 0; + // open PTP sockets + open_sockets_at_port(NULL, 319, &sockets_open_stuff); + open_sockets_at_port(NULL, 320, &sockets_open_stuff); + epoll_fd = -1; // control-c (SIGINT) cleanly @@ -191,6 +215,26 @@ act2.sa_handler = termHandler; sigaction(SIGTERM, &act2, NULL); +#ifdef CONFIG_FOR_OPENBSD + // shm_open(3) prohibits sharing between different UIDs, so nqptp must run as + // the same user shairport-sync does. + struct passwd *pw; + const char *shairport_user = "_shairport"; + pw = getpwnam(shairport_user); + if (pw == NULL) { + die("unknown user %s", shairport_user); + } + if (setgroups(1, &pw->pw_gid) == -1 || + setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 || + setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) { + die("cannot drop privileges to %s", shairport_user); + } + + if (pledge("stdio tmppath inet dns", NULL) == -1) { + die("pledge: %s", strerror(errno)); + } +#endif + // open the SMI shm_fd = -1; @@ -198,7 +242,7 @@ mode_t oldumask = umask(0); shm_fd = shm_open(NQPTP_INTERFACE_NAME, O_RDWR | O_CREAT, 0644); if (shm_fd == -1) { - die("cannot open shared memory \"%s\".", NQPTP_INTERFACE_NAME); + die("nqptp cannot open the shared memory \"%s\" for writing. Is another copy of nqptp (e.g. an nqptp daemon) running already?", NQPTP_INTERFACE_NAME); } (void)umask(oldumask); @@ -206,7 +250,7 @@ die("failed to set size of shared memory \"%s\".", NQPTP_INTERFACE_NAME); } -#ifdef CONFIG_FOR_FREEBSD +#if defined(CONFIG_FOR_FREEBSD) || defined(CONFIG_FOR_OPENBSD) shared_memory = (struct shm_structure *)mmap(NULL, sizeof(struct shm_structure), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); #endif @@ -233,10 +277,7 @@ char buf[BUFLEN]; - // open sockets 319 and 320 - - open_sockets_at_port(NULL, 319, &sockets_open_stuff); - open_sockets_at_port(NULL, 320, &sockets_open_stuff); + // open control socket open_sockets_at_port("localhost", NQPTP_CONTROL_PORT, &sockets_open_stuff); // this for messages from the client diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nqptp-1.2.4/nqptp.service.in new/nqptp-1.2.8/nqptp.service.in --- old/nqptp-1.2.4/nqptp.service.in 2023-09-16 19:51:55.000000000 +0200 +++ new/nqptp-1.2.8/nqptp.service.in 2026-05-13 16:33:47.000000000 +0200 @@ -6,8 +6,9 @@ [Service] ExecStart=@prefix@/bin/nqptp -User=nqptp -Group=nqptp +DynamicUser=yes +LimitRTPRIO=6 +AmbientCapabilities=CAP_NET_BIND_SERVICE [Install] WantedBy=multi-user.target
