#!/data/data/com.termux/files/usr/bin/bash # resolve: hostname -> IP # Order: mdns (zeroconf) -> mdns-resolve (stdlib) -> Tailscale DNS -> local cache # Use in any command: # ping $(resolve lenovo) / curl "http://$(resolve hp62a)" set -e HOST="${1:-}" [[ -z "$HOST" ]] && { echo "Usage: resolve " >&2; exit 1; } CACHE="$HOME/.ssh/resolve-cache" TAILSCALE_DOMAIN="${TAILSCALE_DOMAIN:-tailb0bb74.ts.net}" MDNS_TIMEOUT="${MDNS_TIMEOUT:-2}" QUERY="${HOST%.local}" QUERY="${QUERY%.${TAILSCALE_DOMAIN}}" declare -A ALIASES=( [dell]="dell-latitude3400" [lenovo]="lenovo-ideapad" ) [[ -n "${ALIASES[$QUERY]:-}" ]] && QUERY="${ALIASES[$QUERY]}" IP="" # 1. mdns (zeroconf-based, richer: retries + TTL cache) if command -v mdns >/dev/null 2>&1; then IP=$(mdns resolve --timeout "$MDNS_TIMEOUT" "$QUERY" 2>/dev/null || true) fi # 2. stdlib fallback (no zeroconf needed) if [[ -z "$IP" ]] && command -v mdns-resolve >/dev/null 2>&1; then IP=$(mdns-resolve "${QUERY}.local" "$MDNS_TIMEOUT" 2>/dev/null || true) fi # 3. Tailscale MagicDNS (off-LAN) if [[ -z "$IP" ]]; then IP=$(python -c "import socket; print(socket.gethostbyname('${QUERY}.${TAILSCALE_DOMAIN}'))" 2>/dev/null || true) fi # 4. Legacy flat cache (last resort) if [[ -z "$IP" && -f "$CACHE" ]]; then IP=$(grep "^${QUERY} " "$CACHE" 2>/dev/null | awk '{print $2}') fi if [[ -z "$IP" ]]; then echo "Error: could not resolve '${HOST}'" >&2 exit 1 fi mkdir -p "$(dirname "$CACHE")" grep -v "^${QUERY} " "$CACHE" > "${CACHE}.tmp" 2>/dev/null || true echo "${QUERY} ${IP}" >> "${CACHE}.tmp" mv "${CACHE}.tmp" "$CACHE" echo "$IP"