#!/bin/bash
# NetworkManager Dispatcher script using direct neighbor targeting for Bluetooth PAN
#
# NM's own DHCP-assigned default route for a bluetooth PAN tether isn't
# always reliable (the phone doesn't always show up as a proper DHCP
# gateway), so this manually discovers the phone's IP via ARP/neighbor
# discovery and adds a route to it directly.

IFACE=$1
ACTION=$2

# keep in sync with bt-wizard's ipv4.route-metric -- deliberately far higher
# (lower priority) than any typical default for ethernet/wifi/usb-gadget
# links, so bluetooth only ever wins the default route when nothing else
# (usb0, wifi, etc) is available
BT_METRIC=700

if [[ "$IFACE" == bnep* ]] && [ "$ACTION" = "up" ]; then
    logger -t bt-gateway "Bluetooth link active on $IFACE. Scanning for peer device..."
    
    # Give the IP assignment a brief moment to settle
    sleep 2
    
    GW=""
    # Loop for up to 5 seconds to allow the phone to talk to the Pi and register in ARP
    for i in {1..5}; do
        # Extract the IP of the only other neighbor device on the bnep0 interface
        GW=$(ip neigh show dev "$IFACE" | awk '{print $1}' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -n1)
        
        if [ -n "$GW" ]; then
            break
        fi
        
        # If the ARP table is empty, send a quick ping to the subnet broadcast 
        # to force the phone to announce itself
        BRD=$(ip addr show dev "$IFACE" | grep 'inet ' | awk '{print $4}')
        if [ -n "$BRD" ]; then
            ping -c 1 -b "$BRD" >/dev/null 2>&1
        fi
        sleep 1
    done

    # If we found the neighbor IP, add OUR OWN route at a deliberately low
    # priority. Never touch any other interface's default route (usb0, wifi,
    # etc) -- the kernel already picks whichever default route has the
    # lowest metric on its own, so this only needs to make sure bluetooth's
    # own route exists and stays properly deprioritized, not seize exclusive
    # control of the routing table (which previously broke usb0/other
    # connections every single time bluetooth came up or reconnected).
    if [[ "$GW" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
        logger -t bt-gateway "Peer identified at $GW. Adding low-priority fallback route via $IFACE..."
        ip route replace default via "$GW" dev "$IFACE" metric "$BT_METRIC"
        logger -t bt-gateway "Bluetooth fallback route added via $GW (metric $BT_METRIC)"
    else
        logger -t bt-gateway "Error: No neighbor device found responding on $IFACE."
    fi
fi
