From dcb4956aa4aa5fe13928d50ccfbf26a7e721c070 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Sun, 24 May 2026 15:37:30 +0100 Subject: [PATCH 1/2] Darwin: Add initial support for macOS Apple route(4) has some limitations as does getifaddrs(3). Basically there is no means of being notified of carrier state because Apple only reports this via media state which is an ioctl. The good news is that we can build macOS on github so we can get some BSD traceability at least. Fixes #524 --- .github/workflows/build.yml | 21 +++++++- compat/crypt/sha256.c | 2 +- configure | 101 +++++++++++++++++++----------------- src/dhcp6.c | 2 + src/dhcpcd.c | 26 ++++++++++ src/if-bsd.c | 51 +++++++++++++++--- src/if.c | 2 + src/if.h | 2 +- src/ipv4.h | 6 ++- src/ipv6nd.c | 2 + src/privsep-bpf.c | 14 +++-- src/privsep-bsd.c | 3 +- src/privsep.c | 2 +- src/sa.h | 1 + 14 files changed, 170 insertions(+), 65 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aef45668..19d21e0b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,6 +10,25 @@ env: CC: clang jobs: + # macos is a good plaform as we know it ships with a sanitier we can use + macos: + strategy: + matrix: + os: [ macos-15, macos-26 ] + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v6 + + - name: Configure + run: ./configure --sanitize + + - name: Build + run: make + + - name: Tests + run: make tests + ubuntu: strategy: matrix: @@ -17,7 +36,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - name: Configure run: ./configure diff --git a/compat/crypt/sha256.c b/compat/crypt/sha256.c index dc145e32..5c6e2635 100644 --- a/compat/crypt/sha256.c +++ b/compat/crypt/sha256.c @@ -36,7 +36,7 @@ #ifdef __GLIBC__ # include #endif -#ifdef BSD +#if defined(BSD) || defined(__APPLE__) # ifndef __QNX__ # include # endif diff --git a/configure b/configure index 5c77cc6a..44ba0d02 100755 --- a/configure +++ b/configure @@ -260,6 +260,10 @@ if [ -z "$OS" ]; then esac # Special case case "$OS" in + darwin*) + # Can't install /libexec + : ${PREFIX:=/usr/local} + ;; dragonfly*) # This means /usr HAS to be mounted not via dhcpcd : ${LIBEXECDIR:=${PREFIX:-/usr}/libexec} @@ -376,7 +380,7 @@ else ALLOW_USR_LIBS=true fi case "$OS" in -linux*|solaris*|sunos*|kfreebsd*|dragonfly*|freebsd*) ;; +darwin*|linux*|solaris*|sunos*|kfreebsd*|dragonfly*|freebsd*) ;; *) # There might be more than one ... for LDELFN in /libexec/ld-elf.so.[0-9]*; do @@ -589,8 +593,7 @@ if [ "$PRIVSEP" = yes ]; then if [ -z "$PRIVSEP_USER" ]; then printf "Detecting a suitable user for dhcpcd ... " for x in _dhcpcd _dhcp dhcpcd; do - home=$(getent passwd $x 2>/dev/null | cut -d: -f6) - if [ -d "$home" ]; then + if id "$x" >/dev/null 2>&1; then PRIVSEP_USER="$x" break fi @@ -649,7 +652,7 @@ _CC=false if $XCC _test.c -o _test >/dev/null 2>&3; then [ -x _test ] && _CC=true fi -rm -f _test.c _test +rm -rf _test.* _test if ! $_CC; then echo $XCC echo "$CC does not create executables" >&2 @@ -672,7 +675,7 @@ EOF else echo "no" fi - rm -f _capsicum.c _capsicum + rm -rf _capsicum.* _capsicum printf "Testing for pledge ... " cat <_pledge.c @@ -687,7 +690,7 @@ EOF else echo "no" fi - rm -f _pledge.c _pledge + rm -rf _pledge.* _pledge fi # This block needs to be after the compiler test due to embedded quotes. @@ -715,7 +718,7 @@ EOF echo "no" echo "DHCPCD_SRCS+= if-linux-wext.c" >>$CONFIG_MK fi - rm -f _nl80211.c _nl80211 + rm -rf _nl80211.* _nl80211 printf "Testing for IN6_ADDR_GEN_MODE_NONE ... " cat <_IN6_ADDR_GEN_MODE_NONE.c @@ -731,7 +734,7 @@ EOF else echo "no" fi - rm -f _IN6_ADDR_GEN_MODE_NONE.c _IN6_ADDR_GEN_MODE_NONE + rm -rf _IN6_ADDR_GEN_MODE_NONE.* _IN6_ADDR_GEN_MODE_NONE else printf "Testing for ifam_pid ... " cat <_ifam_pid.c @@ -747,7 +750,7 @@ EOF else echo "no" fi - rm -f _ifam_pid.c _ifam_pid + rm -rf _ifam_pid.* _ifam_pid printf "Testing for ifam_addrflags ... " cat <_ifam_addrflags.c @@ -763,7 +766,7 @@ EOF else echo "no" fi - rm -f _ifam_addrflags.c _ifam_addrflags + rm -rf _ifam_addrflags.* _ifam_addrflags fi abort=false @@ -789,7 +792,7 @@ else echo "libc support for getifaddrs is required - aborting" >&2 abort=true fi -rm -f _getifaddrs.c _getifaddrs +rm -rf _getifaddrs.* _getifaddrs $abort && exit 1 printf "Testing for ifaddrs.ifa_addrflags ... " @@ -808,7 +811,7 @@ if $XCC _getifaddrs_addrflags.c -o _getifaddrs_addrflags $LIBSOCKET 2>&3; then else echo "no" fi -rm -f _getifaddrs_addrflags.c _getifaddrs_addrflags +rm -rf _getifaddrs_addrflags.* _getifaddrs_addrflags printf "Testing for clock_gettime ... " cat <_clock_gettime.c @@ -828,7 +831,7 @@ else echo "libc support for clock_getttime is required - aborting" >&2 abort=true fi -rm -f _clock_gettime.c _clock_gettime +rm -rf _clock_gettime.* _clock_gettime $abort && exit 1 if [ -z "$CLOSEFROM" ]; then @@ -848,7 +851,7 @@ EOF fi echo "$CLOSEFROM" fi -rm -f _closefrom.c _closefrom +rm -rf _closefrom.* _closefrom if [ "$CLOSEFROM" = no ]; then echo "COMPAT_SRCS+= compat/closefrom.c" >>$CONFIG_MK echo "#include \"compat/closefrom.h\"" >>$CONFIG_H @@ -873,7 +876,7 @@ echo "$IOCTL_REQ" if [ "$IOCTL_REQ" != "unsigned long" ]; then echo "#define IOCTL_REQUEST_TYPE $IOCTL_REQ" >>$CONFIG_H fi -rm -f _ioctl.c _ioctl +rm -rf _ioctl.* _ioctl printf "Testing for inet_ntoa ... " cat <_inet_ntoa.c @@ -898,7 +901,7 @@ else echo "libc support for inet_ntoa is required - aborting" >&2 abort=true fi -rm -f _inet_ntoa.c _inet_ntoa +rm -rf _inet_ntoa.* _inet_ntoa $abort && exit 1 if [ -z "$ARC4RANDOM" ]; then @@ -915,7 +918,7 @@ EOF ARC4RANDOM=no fi echo "$ARC4RANDOM" - rm -f _arc4random.c _arc4random + rm -rf _arc4random.* _arc4random fi if [ "$ARC4RANDOM" = no ]; then echo "COMPAT_SRCS+= compat/arc4random.c" >>$CONFIG_MK @@ -936,7 +939,7 @@ EOF ARC4RANDOM_UNIFORM=no fi echo "$ARC4RANDOM_UNIFORM" - rm -f _arc4random_uniform.c _arc4random_uniform + rm -rf _arc4random_uniform.* _arc4random_uniform fi if [ "$ARC4RANDOM_UNIFORM" = no ]; then echo "COMPAT_SRCS+= compat/arc4random_uniform.c" >>$CONFIG_MK @@ -960,7 +963,7 @@ EOF MEMSET_EXPLICIT=no fi echo "$MEMSET_EXPLICIT" - rm -f _memset_explicit.c _memset_explicit + rm -rf _memset_explicit.* _memset_explicit fi if [ "$MEMSET_EXPLICIT" = yes ]; then echo "#define HAVE_MEMSET_EXPLICIT" >>$CONFIG_H @@ -983,7 +986,7 @@ EOF EXPLICIT_BZERO=no fi echo "$EXPLICIT_BZERO" - rm -f _explicit_bzero.c _explicit_bzero + rm -rf _explicit_bzero.* _explicit_bzero fi if [ "$EXPLICIT_BZERO" = yes ]; then echo "#define HAVE_EXPLICIT_BZERO" >>$CONFIG_H @@ -1006,7 +1009,7 @@ EOF MEMSET_S=no fi echo "$MEMSET_S" - rm -f _memset_s.c _memset_s + rm -rf _memset_s.* _memset_s fi if [ "$MEMSET_S" = yes ]; then echo "#define __STDC_WANT_LIB_EXT1__ 1" >>$CONFIG_H @@ -1027,7 +1030,7 @@ EOF OPEN_MEMSTREAM=no fi echo "$OPEN_MEMSTREAM" - rm -f _open_memstream.c _open_memstream + rm -rf _open_memstream.* _open_memstream fi if [ "$OPEN_MEMSTREAM" = yes ]; then echo "#define HAVE_OPEN_MEMSTREAM" >>$CONFIG_H @@ -1059,7 +1062,7 @@ EOF PIDFILE_LOCK=no fi echo "$PIDFILE_LOCK" - rm -f _pidfile.c _pidfile + rm -rf _pidfile.* _pidfile fi if [ "$PIDFILE_LOCK" = no ]; then echo "COMPAT_SRCS+= compat/pidfile.c" >>$CONFIG_MK @@ -1087,11 +1090,11 @@ EOF SETPROCTITLE=no fi echo "$SETPROCTITLE" - rm -f _setproctitle.c _setproctitle + rm -rf _setproctitle.* _setproctitle fi if [ "$SETPROCTITLE" = no ]; then case "$OS" in - solaris*|sunos*) + darwin*|solaris*|sunos*) echo "$OS has no support for setting process title" echo "#define setproctitle(...)" >>$CONFIG_H ;; @@ -1099,9 +1102,13 @@ if [ "$SETPROCTITLE" = no ]; then echo "COMPAT_SRCS+= compat/setproctitle.c" >>$CONFIG_MK echo "#include \"compat/setproctitle.h\"" \ >>$CONFIG_H + SETPROCTITLE=yes ;; esac fi +if [ "$SETPROCTITLE" = yes ]; then + echo "#define HAVE_SETPROCTITLE" >>$CONFIG_H +fi if [ -z "$STRLCPY" ]; then printf "Testing for strlcpy ... " @@ -1119,7 +1126,7 @@ EOF STRLCPY=no fi echo "$STRLCPY" - rm -f _strlcpy.c _strlcpy + rm -rf _strlcpy.* _strlcpy fi if [ "$STRLCPY" = no ]; then echo "COMPAT_SRCS+= compat/strlcpy.c" >>$CONFIG_MK @@ -1143,7 +1150,7 @@ EOF STRTOI=no fi echo "$STRTOI" - rm -f _strtoi.c _strtoi + rm -rf _strtoi.* _strtoi fi if [ "$STRTOI" = no ]; then echo "COMPAT_SRCS+= compat/strtoi.c compat/strtou.c" >>$CONFIG_MK @@ -1164,7 +1171,7 @@ EOF CONSTTIME_MEMEQUAL=no fi echo "$CONSTTIME_MEMEQUAL" - rm -f _consttime_memequal.c _consttime_memequal + rm -rf _consttime_memequal.* _consttime_memequal fi if [ "$CONSTTIME_MEMEQUAL" = no ] && [ -z "$TIMINGSAFE_BCMP" ]; then printf "Testing for timingsafe_bcmp ... " @@ -1180,7 +1187,7 @@ EOF TIMINGSAFE_BCMP=no fi echo "$TIMINGSAFE_BCMP" - rm -f _timingsafe_bcmp.c _timingsafe_bcmp + rm -rf _timingsafe_bcmp.* _timingsafe_bcmp fi if [ "$CONSTTIME_MEMEQUAL" = no ]; then @@ -1207,7 +1214,7 @@ EOF DPRINTF=no fi echo "$DPRINTF" - rm -f _dprintf.c _dprintf + rm -rf _dprintf.* _dprintf fi if [ "$DPRINTF" = no ]; then echo "COMPAT_SRCS+= compat/dprintf.c" >>$CONFIG_MK @@ -1231,7 +1238,7 @@ EOF RBTREE=no fi echo "$RBTREE" - rm -f _rbtree.c _rbtree + rm -rf _rbtree.* _rbtree fi if [ "$RBTREE" = no ]; then echo "VENDOR_SRCS+= vendor/rbtree.c" >>$CONFIG_MK @@ -1261,7 +1268,7 @@ EOF REALLOCARRAY=no fi echo "$REALLOCARRAY" - rm -f _reallocarray.c _reallocarray + rm -rf _reallocarray.* _reallocarray fi if [ "$REALLOCARRAY" = no ]; then echo "COMPAT_SRCS+= compat/reallocarray.c" >>$CONFIG_MK @@ -1286,7 +1293,7 @@ EOF BE64ENC=no fi echo "$BE64ENC" - rm -f _be64enc.c _be64enc + rm -rf _be64enc.* _be64enc fi if [ "$BE64ENC" = no ]; then echo "#include \"compat/endian.h\"" >>$CONFIG_H @@ -1306,7 +1313,7 @@ EOF FLS64=no fi echo "$FLS64" - rm -f _fls64.c _fls64 + rm -rf _fls64.* _fls64 fi if [ "$FLS64" = yes ]; then echo "#define HAVE_SYS_BITOPS_H" >>$CONFIG_H @@ -1340,7 +1347,7 @@ EOF MD5=no fi echo "$MD5" - rm -f _md5.c _md5 + rm -rf _md5.* _md5 fi if [ -z "$SHA2_H" ]; then @@ -1390,7 +1397,7 @@ EOF SHA2=no fi echo "$SHA2" - rm -f _sha256.c _sha256 + rm -rf _sha256.* _sha256 if [ "$SHA2" = no ]; then # Did OpenBSD really change this? grrrr printf "Testing for SHA256Init ... " @@ -1424,7 +1431,7 @@ EOF SHA2=no fi echo "$SHA2" - rm -f _sha256.c _sha256 + rm -rf _sha256.* _sha256 fi fi @@ -1457,7 +1464,7 @@ EOF fi fi echo "$HMAC" - rm -f _hmac.c _hmac + rm -rf _hmac.* _hmac fi if [ "$OPENSSL" = yes ] || @@ -1491,7 +1498,7 @@ EOF OPENSSL=no fi echo "$OPENSSL" - rm -f _openssl.c _openssl + rm -rf _openssl.* _openssl fi if [ "$OPENSSL" = yes ]; then @@ -1516,7 +1523,7 @@ EOF SHA2_LIB= SHA2_RENAMED= echo "$SHA2" - rm -f _openssl_sha.c _openssl_sha + rm -rf _openssl_sha.* _openssl_sha fi if [ "$LIBPCAP" = yes ]; then @@ -1542,7 +1549,7 @@ EOF echo "no" abort=true fi - rm -f _libpcap.c libpcap + rm -rf _libpcap.* libpcap $abort && exit 1 fi echo "CFLAGS+= $LIBPCAP_CFLAGS" >>$CONFIG_MK @@ -1563,7 +1570,7 @@ EOF else echo "no" fi - rm -f _libpcap_imm.c libpcap_imm + rm -rf _libpcap_imm.* libpcap_imm printf "Testing for pcap_setwritefilter() ... " cat <_libpcap_write.c @@ -1579,7 +1586,7 @@ EOF else echo "no" fi - rm -f _libpcap_write.c libpcap_write + rm -rf _libpcap_write.* libpcap_write printf "Testing for pcap_lockfilter() ... " cat <_libpcap_lock.c @@ -1595,7 +1602,7 @@ EOF else echo "no" fi - rm -f _libpcap_lock.c libpcap_lock + rm -rf _libpcap_lock.* libpcap_lock fi # Workaround for DragonFlyBSD import @@ -1709,7 +1716,7 @@ EOF echo "LIBUDEV_CPPFLAGS+= -DLIBUDEV_NOFILTER" >>$CONFIG_MK echo "no" fi - rm -f _udev.c _udev + rm -rf _udev.* _udev printf "Checking udev_device_get_is_initialized ... " cat <_udev.c @@ -1726,7 +1733,7 @@ EOF echo "LIBUDEV_CPPFLAGS+= -DLIBUDEV_NOINIT" >>$CONFIG_MK echo "no" fi - rm -f _udev.c _udev + rm -rf _udev.* _udev elif [ "$DEV" != no ] && [ "$UDEV" != no ] && [ -n "$UDEV" ]; then echo "udev has been explicitly requested ... aborting" >&2 exit 1 @@ -1761,7 +1768,7 @@ EOF echo "no" echo "libc for dlopen is required - aborting" fi - rm -f _dlopen.c _dlopen + rm -rf _dlopen.* _dlopen $abort && exit 1 fi diff --git a/src/dhcp6.c b/src/dhcp6.c index d9e8b709..c734c8ae 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -26,6 +26,8 @@ * SUCH DAMAGE. */ +#define __APPLE_USE_RFC_3542 + #include #include diff --git a/src/dhcpcd.c b/src/dhcpcd.c index b5c5ae28..81989478 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -1984,6 +1984,28 @@ dup_null(int fd) return err; } +#ifdef __APPLE__ +static void +dhcpcd_poll_carrier(void *arg) +{ + struct dhcpcd_ctx *ctx = arg; + struct interface *ifp; + int link_status; + + if (ctx->options & DHCPCD_EXITING) + return; + + TAILQ_FOREACH(ifp, ctx->ifaces, next) { + if (!(ifp->active)) + continue; + link_status = if_carrier(ifp, NULL); + dhcpcd_handlecarrier(ifp, link_status, ifp->flags); + } + + eloop_timeout_add_sec(ctx->eloop, 1, dhcpcd_poll_carrier, ctx); +} +#endif + int main(int argc, char **argv, char **envp) { @@ -2721,6 +2743,10 @@ main(int argc, char **argv, char **envp) dhcpcd_prestartinterface, ifp); } +#ifdef __APPLE__ + dhcpcd_poll_carrier(&ctx); +#endif + run_loop: i = eloop_start(ctx.eloop); if (i < 0) { diff --git a/src/if-bsd.c b/src/if-bsd.c index c533e024..bf11738f 100644 --- a/src/if-bsd.c +++ b/src/if-bsd.c @@ -50,16 +50,23 @@ #include #include "config.h" +#include "src/dhcpcd.h" #ifdef __NetBSD__ #include /* Needs netinet/if_ether.h */ #elif defined(__DragonFly__) #include +#elif defined(__APPLE__) +/* Apple doesn't ship this in include/net ... */ +struct vlanreq { + char vlr_parent[IFNAMSIZ]; + u_short vlr_tag; +}; #else #include #endif #ifdef __DragonFly__ #include -#else +#elif !defined(__APPLE__) #include #include #endif @@ -96,11 +103,15 @@ #include "sa.h" #ifndef RT_ROUNDUP +#ifdef __APPLE__ +#define RT_ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t)) +#else #define RT_ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#endif #define RT_ADVANCE(x, n) (x += RT_ROUNDUP((n)->sa_len)) #endif - /* Ignore these interface names which look like ethernet but are virtual or * just won't work without explicit configuration. */ static const char *const ifnames_ignore[] = { "bridge", @@ -108,6 +119,9 @@ static const char *const ifnames_ignore[] = { "bridge", "fwe", /* Firewire */ "fwip", /* Firewire */ "tap", "vether", "xvif", /* XEN DOM0 -> guest interface */ +#ifdef __APPLE__ + "ap", "awdl", "llw", +#endif NULL }; struct rtm { @@ -227,7 +241,7 @@ if_opensockets_os(struct dhcpcd_ctx *ctx) ps_rights_limit_fd_sockopt(ctx->link_fd); #endif -#if defined(SIOCALIFADDR) && defined(IFLR_ACTIVE) /*NetBSD */ +#if (defined(SIOCALIFADDR) && defined(IFLR_ACTIVE)) priv->pf_link_fd = xsocket(PF_LINK, SOCK_DGRAM, 0); if (priv->pf_link_fd == -1) logerr("%s: socket(PF_LINK)", __func__); @@ -400,6 +414,7 @@ if_indirect_ioctl(struct dhcpcd_ctx *ctx, const char *ifname, unsigned long cmd, int if_carrier(struct interface *ifp, const void *ifadata) { +#ifdef LINK_STATE_UP const struct if_data *ifi = ifadata; /* @@ -408,7 +423,6 @@ if_carrier(struct interface *ifp, const void *ifadata) * support SIOCGIFMEDIA. */ assert(ifadata != NULL); - if (ifi->ifi_link_state >= LINK_STATE_UP) return LINK_UP; if (ifi->ifi_link_state == LINK_STATE_UNKNOWN) { @@ -421,6 +435,23 @@ if_carrier(struct interface *ifp, const void *ifadata) return LINK_UNKNOWN; } return LINK_DOWN; +#elif defined(SIOCGIFXMEDIA) + struct dhcpcd_ctx *ctx = ifp->ctx; + struct ifmediareq ifmr = { .ifm_active = 0 }; + int error; + + strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name)); + if (ioctl(ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr) == -1) + return LINK_UNKNOWN; + if (!(ifmr.ifm_status & IFM_AVALID)) + return LINK_UNKNOWN; + return ifmr.ifm_status & IFM_ACTIVE ? LINK_UP : LINK_DOWN; +#else +#warning OS does not report interface link state + UNUSED(ifp); + UNUSED(ifadata); + return LINK_UNKNOWN; +#endif } bool @@ -489,6 +520,10 @@ if_getssid1(struct dhcpcd_ctx *ctx, const char *ifname, void *ssid) } } #else +#warning OS does not report interface SSID + UNUSED(ctx); + UNUSED(ifname); + UNUSED(ssid); errno = ENOSYS; #endif @@ -528,7 +563,7 @@ if_vimaster(struct dhcpcd_ctx *ctx, const char *ifname) return -1; if (ifmr.ifm_status & IFM_AVALID && IFM_TYPE(ifmr.ifm_active) == IFM_IEEE80211) { - if (if_getssid1(ctx, ifname, NULL) == -1) + if (if_getssid1(ctx, ifname, NULL) == -1 && errno != ENOSYS) return 1; } return 0; @@ -537,7 +572,7 @@ if_vimaster(struct dhcpcd_ctx *ctx, const char *ifname) unsigned short if_vlanid(const struct interface *ifp) { -#ifdef SIOCGETVLAN +#if defined(SIOCGETVLAN) struct vlanreq vlr = { .vlr_tag = 0 }; if (if_indirect_ioctl(ifp->ctx, ifp->name, SIOCGETVLAN, &vlr, @@ -929,7 +964,7 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm) } static int -if_sysctl(struct dhcpcd_ctx *ctx, const int *name, u_int namelen, void *oldp, +if_sysctl(struct dhcpcd_ctx *ctx, int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { #if defined(PRIVSEP) && defined(HAVE_CAPSICUM) @@ -1225,6 +1260,7 @@ if_getlifetime6(struct ipv6_addr *ia) } #endif +#ifdef IFAN_ARRIVAL static int if_announce(struct dhcpcd_ctx *ctx, const struct if_announcemsghdr *ifan) { @@ -1242,6 +1278,7 @@ if_announce(struct dhcpcd_ctx *ctx, const struct if_announcemsghdr *ifan) return 0; } +#endif static int if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm) diff --git a/src/if.c b/src/if.c index e807acda..d1b4a02c 100644 --- a/src/if.c +++ b/src/if.c @@ -26,6 +26,8 @@ * SUCH DAMAGE. */ +#define __APPLE_USE_RFC_3542 + #include #include #include diff --git a/src/if.h b/src/if.h index 6150bca8..f4e14bd0 100644 --- a/src/if.h +++ b/src/if.h @@ -128,7 +128,7 @@ struct priv { #ifdef INET6 int pf_inet6_fd; #endif -#if defined(SIOCALIFADDR) && defined(IFLR_ACTIVE) /*NetBSD */ +#if (defined(SIOCALIFADDR) && defined(IFLR_ACTIVE)) || defined(SIOCGIFSTATUS) int pf_link_fd; #endif }; diff --git a/src/ipv4.h b/src/ipv4.h index af3c73eb..90c9110c 100644 --- a/src/ipv4.h +++ b/src/ipv4.h @@ -77,8 +77,12 @@ (IN_IFF_TENTATIVE | IN_IFF_DUPLICATED | IN_IFF_DETACHED) #endif -#define IN_ARE_ADDR_EQUAL(a, b) ((a)->s_addr == (b)->s_addr) +#ifndef IN_ARE_ADDR_EQUAL +#define IN_ARE_ADDR_EQUAL(a, b) ((a)->s_addr == (b)->s_addr) +#endif +#ifndef IN_IS_ADDR_UNSPECIFIED #define IN_IS_ADDR_UNSPECIFIED(a) ((a)->s_addr == INADDR_ANY) +#endif #ifdef __linux__ #define IP_LIFETIME diff --git a/src/ipv6nd.c b/src/ipv6nd.c index eafcf4c9..68edf7ad 100644 --- a/src/ipv6nd.c +++ b/src/ipv6nd.c @@ -26,6 +26,8 @@ * SUCH DAMAGE. */ +#define __APPLE_USE_RFC_3542 + #include #include #include diff --git a/src/privsep-bpf.c b/src/privsep-bpf.c index 940c576e..86da7e47 100644 --- a/src/privsep-bpf.c +++ b/src/privsep-bpf.c @@ -149,16 +149,20 @@ static int ps_bpf_start_bpf(struct ps_process *psp) { struct dhcpcd_ctx *ctx = psp->psp_ctx; - char *addr; struct in_addr *ia = &psp->psp_id.psi_addr.psa_in_addr; +#ifdef HAVE_SETPROCTITLE + char *addr; +#endif - if (ia->s_addr == INADDR_ANY) { + if (ia->s_addr == INADDR_ANY) ia = NULL; - addr = NULL; - } else - addr = inet_ntoa(*ia); + +#ifdef HAVE_SETPROCTITLE + addr = ia != NULL ? inet_ntoa(*ia) : NULL; setproctitle("[BPF %s] %s%s%s", psp->psp_protostr, psp->psp_ifname, addr != NULL ? " " : "", addr != NULL ? addr : ""); +#endif + ps_freeprocesses(ctx, psp); psp->psp_bpf = bpf_open(&psp->psp_ifp, psp->psp_filter, ia); diff --git a/src/privsep-bsd.c b/src/privsep-bsd.c index 836a9df9..42bc45eb 100644 --- a/src/privsep-bsd.c +++ b/src/privsep-bsd.c @@ -43,12 +43,13 @@ #include #elif defined(__DragonFly__) #include +#elif defined(__APPLE__) #else #include #endif #ifdef __DragonFly__ #include -#else +#elif !defined(__APPLE__) #include #include #endif diff --git a/src/privsep.c b/src/privsep.c index 33d8aeb5..93100acb 100644 --- a/src/privsep.c +++ b/src/privsep.c @@ -127,7 +127,7 @@ ps_dropprivs(struct dhcpcd_ctx *ctx) struct passwd *pw = ctx->ps_user; int fd_out = ctx->options & DHCPCD_DUMPLEASE ? STDOUT_FILENO : STDERR_FILENO; - +return 0; if (ctx->options & DHCPCD_LAUNCHER) #ifdef ASAN logwarnx("not chrooting as compiled for ASAN"); diff --git a/src/sa.h b/src/sa.h index 4083d561..e40d68fe 100644 --- a/src/sa.h +++ b/src/sa.h @@ -37,6 +37,7 @@ union sa_ss { struct sockaddr sa; struct sockaddr_in sin; struct sockaddr_in6 sin6; +// struct sockaddr_storage ss; /* avoids memory overrun */ }; #ifdef BSD From 8b20429ad75a99ecf02c17520ca6cef079748d02 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Sun, 24 May 2026 16:09:52 +0100 Subject: [PATCH 2/2] Address review comments --- .github/workflows/build.yml | 4 ++-- src/dhcpcd.c | 1 + src/if-bsd.c | 4 ++-- src/privsep.c | 2 +- tests/eloop-bench/eloop-bench.c | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 19d21e0b..84a4015d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,11 +10,11 @@ env: CC: clang jobs: - # macos is a good plaform as we know it ships with a sanitier we can use + # macos is a good platform as we know it ships with a sanitizer we can use macos: strategy: matrix: - os: [ macos-15, macos-26 ] + os: [ macos-26 ] runs-on: ${{ matrix.os }} steps: diff --git a/src/dhcpcd.c b/src/dhcpcd.c index 81989478..1fa7c3ab 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -1985,6 +1985,7 @@ dup_null(int fd) } #ifdef __APPLE__ +#warning OS does not report interface link state change, polling every second static void dhcpcd_poll_carrier(void *arg) { diff --git a/src/if-bsd.c b/src/if-bsd.c index bf11738f..72d573b7 100644 --- a/src/if-bsd.c +++ b/src/if-bsd.c @@ -438,10 +438,10 @@ if_carrier(struct interface *ifp, const void *ifadata) #elif defined(SIOCGIFXMEDIA) struct dhcpcd_ctx *ctx = ifp->ctx; struct ifmediareq ifmr = { .ifm_active = 0 }; - int error; + UNUSED(ifadata); strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name)); - if (ioctl(ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr) == -1) + if (ioctl(ctx->pf_inet_fd, SIOCGIFXMEDIA, &ifmr) == -1) return LINK_UNKNOWN; if (!(ifmr.ifm_status & IFM_AVALID)) return LINK_UNKNOWN; diff --git a/src/privsep.c b/src/privsep.c index 93100acb..33d8aeb5 100644 --- a/src/privsep.c +++ b/src/privsep.c @@ -127,7 +127,7 @@ ps_dropprivs(struct dhcpcd_ctx *ctx) struct passwd *pw = ctx->ps_user; int fd_out = ctx->options & DHCPCD_DUMPLEASE ? STDOUT_FILENO : STDERR_FILENO; -return 0; + if (ctx->options & DHCPCD_LAUNCHER) #ifdef ASAN logwarnx("not chrooting as compiled for ASAN"); diff --git a/tests/eloop-bench/eloop-bench.c b/tests/eloop-bench/eloop-bench.c index 984c2e8b..bd177f33 100644 --- a/tests/eloop-bench/eloop-bench.c +++ b/tests/eloop-bench/eloop-bench.c @@ -158,7 +158,7 @@ main(int argc, char **argv) err(EXIT_FAILURE, "malloc"); for (i = 0, p = pipes; i < npipes; i++, p++) { - if (pipe2(p->fd, O_CLOEXEC | O_NONBLOCK) == -1) + if (pipe(p->fd) == -1) err(EXIT_FAILURE, "pipe"); if (eloop_event_add(e, p->fd[0], ELE_READ, read_cb, p) == -1) err(EXIT_FAILURE, "eloop_event_add");