diff --git a/.chezmoiignore b/.chezmoiignore index 7dbcb70..73125a2 100644 --- a/.chezmoiignore +++ b/.chezmoiignore @@ -3,6 +3,14 @@ Library .terminfo .1password .config/karabiner +# macOS-only: the ping wrapper drives /sbin/ping6 and dscacheutil, and ping4 +# is a symlink to /sbin/ping. Linux ping picks a family itself and takes -4. +.local/bin/ping +.local/bin/ping4 +{{- end }} +{{- if eq .chezmoi.os "darwin" }} +# Linux-only: macOS ping rejects -4, so there ping4 is ~/.local/bin/ping4. +.config/fish/functions/ping4.fish {{- end }} .config/karabiner/automatic_backups .config/scripts/__pycache__ diff --git a/private_dot_config/private_fish/functions/ping4.fish b/private_dot_config/private_fish/functions/ping4.fish new file mode 100644 index 0000000..c243863 --- /dev/null +++ b/private_dot_config/private_fish/functions/ping4.fish @@ -0,0 +1,5 @@ +function ping4 --description 'Ping over IPv4' + # Linux only -- .chezmoiignore keeps this off macOS, where ping has no -4 + # flag and ~/.local/bin/ping4 points at /sbin/ping instead. + command ping -4 $argv +end diff --git a/private_dot_local/bin/executable_ping b/private_dot_local/bin/executable_ping new file mode 100644 index 0000000..00e3c64 --- /dev/null +++ b/private_dot_local/bin/executable_ping @@ -0,0 +1,48 @@ +#!/bin/sh +# Unified ping, native output preserved. +# +# macOS still ships separate ping/ping6 binaries, so this picks one the way +# Linux's ping does: IPv6 when the target has an AAAA record *and* this machine +# can actually reach over IPv6, IPv4 otherwise. + +v6_usable() { + # A default route on its own is not enough. A Mac with IPv6 switched off + # can still show a default v6 route while holding only ::1 and fe80:: + # link-local addresses, and ping6 then dies with "No route to host". + # Global unicast is 2000::/3, so require an address starting with 2 or 3. + route -n get -inet6 default >/dev/null 2>&1 || return 1 + ifconfig 2>/dev/null | awk '/inet6 /{ print $2 }' | grep -qE '^[23]' +} + +case "$1" in + -6) + shift + exec /sbin/ping6 "$@" + ;; + -4) + shift + exec /sbin/ping "$@" + ;; + *:*) + # An explicit IPv6 literal: honour it and let ping6 report any problem. + exec /sbin/ping6 "$@" + ;; +esac + +# First non-option argument is the target. +for a in "$@"; do + case "$a" in + -*) ;; + *) + t="$a" + break + ;; + esac +done + +if [ -n "$t" ] && v6_usable && + dscacheutil -q host -a name "$t" 2>/dev/null | grep -q ipv6_address; then + exec /sbin/ping6 "$@" +fi + +exec /sbin/ping "$@" diff --git a/private_dot_local/bin/symlink_ping4 b/private_dot_local/bin/symlink_ping4 new file mode 100644 index 0000000..4aa6e7b --- /dev/null +++ b/private_dot_local/bin/symlink_ping4 @@ -0,0 +1 @@ +/sbin/ping