#!/usr/bin/env bash # This script depends on the following applications: # bash # sshpass # jq # curl # UniFi Controller credentials CONTROLLER_URL="https://your-controller-url:8443" # Replace with your Unifi Controller Domain name or IP:PORT USERNAME="your-username" # Replace with your Unifi Controller username PASSWORD="your-password" # Replace with your Unifi Controller password SITE_NAME="default" # Replace with your site name if different SSH_USERNAME="your-username" # Replace with your SSH username SSH_PASSWORD="your-password" # Replace with your SSH password ######################################################################################################### ###### Do not edit below this, unless you know what you are doing. :-) ################################# ##### Script made by Dennis Juhler Aagaard ################################# ##### License is BSD 0-Clause ################################# # Copyright (C) 2024 by Dennis Juhler Aagaard ################################# # Permission to use, copy, modify, and/or distribute this software for ################################# # any purpose with or without fee is hereby granted. ################################# # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL ################################# # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED ################################# # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ################################# # THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR ################################# # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS ################################# # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE ################################# # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH ################################# # THE USE OR PERFORMANCE OF THIS SOFTWARE ################################# ######################################################################################################### if command -v sshpass &> /dev/null; then echo "sshpass is installed" else echo "sshpass is not installed." echo "install it by running your favourite pkg manager." exit 1 fi if command -v jq &> /dev/null; then echo "jq is installed" else echo "jq is not installed." echo "install it by running your favourite pkg manager." exit 1 fi if command -v curl &> /dev/null; then echo "curl is installed" else echo "curl is not installed." echo "install it by running your favourite pkg manager." exit 1 fi echo "" # Function to retrieve site ID get_site_id() { SITES_RESPONSE=$(curl --silent --insecure --cookie /tmp/unifi_cookie \ ${CONTROLLER_URL}/api/self/sites) if [[ $(echo "$SITES_RESPONSE" | jq -r '.meta.rc') != "ok" ]]; then echo "Failed to retrieve sites: $(echo "$SITES_RESPONSE" | jq -r '.meta.msg')" >&2 exit 1 fi SITE_ID=$(echo "$SITES_RESPONSE" | jq -r --arg site_name "$SITE_NAME" '.data[] | select(.desc == $site_name) | .name') if [[ -z "$SITE_ID" ]]; then echo "Site '$SITE_NAME' not found." >&2 exit 1 fi } # Function to get the 2.4GHz radio MAC address using sshpass get_radio_mac() { local AP_IP=$1 # Determine the hardware architecture and set the interface name ARCHITECTURE=$(sshpass -p "$SSH_PASSWORD" ssh -o StrictHostKeyChecking=no $SSH_USERNAME@$AP_IP "uname -a") if echo "$ARCHITECTURE" | grep -q 'aarch64'; then INTERFACE='ra0' else INTERFACE='ath0' fi #echo "Using interface $INTERFACE for $AP_IP" if [ $INTERFACE = 'ra0' ]; then # Retrieve the MAC address for the determined interface MAC_ADDRESS=$(sshpass -p "$SSH_PASSWORD" ssh -o StrictHostKeyChecking=no $SSH_USERNAME@$AP_IP \ "iwconfig $INTERFACE 2>/dev/null | grep 'Access Point' | awk '{print \$5}'") fi if [ $INTERFACE = 'ath0' ]; then # Retrieve the MAC address for the determined interface MAC_ADDRESS=$(sshpass -p "$SSH_PASSWORD" ssh -o StrictHostKeyChecking=no $SSH_USERNAME@$AP_IP \ "iwconfig $INTERFACE 2>/dev/null | grep 'Access Point' | awk '{print \$6}'") fi echo "$MAC_ADDRESS" } # Login to UniFi Controller and get a session cookie LOGIN_RESPONSE=$(curl --silent --insecure --cookie-jar /tmp/unifi_cookie \ --data "{\"username\":\"${USERNAME}\",\"password\":\"${PASSWORD}\"}" \ --header 'Content-Type: application/json' \ ${CONTROLLER_URL}/api/login) # Check if login was successful if [[ $(echo "$LOGIN_RESPONSE" | jq -r '.meta.rc') != "ok" ]]; then echo "Login failed: $(echo "$LOGIN_RESPONSE" | jq -r '.meta.msg')" >&2 exit 1 fi # Retrieve the correct site ID get_site_id # Get the list of devices and filter for WiFi access points DEVICE_LIST=$(curl --silent --insecure --cookie /tmp/unifi_cookie \ ${CONTROLLER_URL}/api/s/${SITE_ID}/stat/device) # Check if device list retrieval was successful if [[ $(echo "$DEVICE_LIST" | jq -r '.meta.rc') != "ok" ]]; then echo "Failed to retrieve device list: $(echo "$DEVICE_LIST" | jq -r '.meta.msg')" >&2 exit 1 fi # Extract AP names and IP addresses AP_LIST=$(echo ${DEVICE_LIST} | jq -r '.data[] | select(.type=="uap") | "\(.name),\(.ip)"') # Output header echo "Access Point Name, 2.4GHz MAC Address" echo "" # Check if AP_LIST is empty and print a message if it is if [ -z "$AP_LIST" ]; then echo "No access points found or unable to retrieve access points. Please check your UniFi Controller settings." exit 1 fi # Read AP names and IP addresses into an array IFS=$'\n' read -d '' -r -a ap_array <<< "$AP_LIST" # Loop through each AP, SSH to get the MAC address, and output the result for AP_INFO in "${ap_array[@]}"; do IFS=, read -r AP_NAME AP_IP <<< "$AP_INFO" #echo "Checking AP: $AP_NAME ($AP_IP)" MAC_ADDRESS=$(get_radio_mac $AP_IP) if [ -z "$MAC_ADDRESS" ]; then COUNT=$((COUNT + 1)) echo "$COUNT" echo "Failed to retrieve MAC address for $AP_NAME ($AP_IP)" else COUNT=$((COUNT + 1)) echo "$COUNT" echo "Unifi AP Name: $AP_NAME" #echo " $AP_IP" echo "MAC Address: $MAC_ADDRESS" echo "" fi done # Logout to clean up the session and suppress output curl --silent --insecure --cookie /tmp/unifi_cookie ${CONTROLLER_URL}/api/logout > /dev/null # Remove the cookie file rm /tmp/unifi_cookie