# Discovering Your Network | A Bash Script to Map IP & LLDP Neighbors

Ever wondered who's hanging out on your local network? Whether you're a network admin, a curious techie, or just want to keep tabs on your devices, this Bash script is your go-to tool for uncovering the devices connected to your network. It leverages Linux commands like `ip`, `nmap`, and `lldpcli`, along with an external API, to provide a detailed snapshot of your network neighbors. In this blog post, we'll dive into what this script does, how it works, and how you can use it to explore your network like a pro.

## What Does the Script Do?

This script is a powerful network discovery tool that generates two detailed tables:

1. **IP Neighbors Table**:
    
    * Lists all IPv4 devices in your local network's ARP table (using `ip neigh show`).
        
    * Excludes IPv6 addresses for a clean focus on IPv4.
        
    * Retrieves the vendor of each device's MAC address using the [`macvendors.com`](http://macvendors.com) API.
        
    * Performs a quick `nmap` scan to identify open TCP ports on each device.
        
    * Outputs a formatted table with columns for **IP Address**, **MAC Address**, **Vendor** (30 characters wide), and **Open Ports**.
        
2. **LLDP Neighbors Summary Table**:
    
    * Uses `lldpcli show neighbors summary` to list devices connected via the Link Layer Discovery Protocol (LLDP), typically used in enterprise networks.
        
    * Displays details like **Interface**, **Chassis ID** (MAC address), **System Name**, and **Port Description**.
        

The script ensures all dependencies (`curl`, `ip`, `nmap`, `lldpcli`) are installed, runs with root privileges (required for `nmap` and `lldpcli`), and handles errors gracefully. It's perfect for network troubleshooting, security audits, or just satisfying your curiosity about what's on your network.

## Example Output

Here's a sample output from running the script on a network with a mix of devices:

```plaintext
IP Neighbors Table:
IP Address      MAC Address       Vendor                         Open Ports
--------------- ----------------- ------------------------------ --------------------
192.168.88.89   00:0b:82:7f:c0:5d Grandstream Networks, Inc.     22/tcp,80/tcp
192.168.88.66   86:34:16:3b:49:02 Unknown                        None
192.168.88.112  80:af:ca:24:1a:84 Shenzhen Cudy Technology Co., Ltd. 53/tcp,80/tcp,443/tcp
192.168.88.6    52:54:00:38:0b:45 Unknown                        22/tcp
192.168.88.250  10:5a:17:16:03:35 Tuya Smart Inc.                None
192.168.88.86   f4:30:b9:c2:11:59 Hewlett Packard                80/tcp,443/tcp,631/tcp,8080/tcp
192.168.88.55   d8:1f:12:30:94:fa Tuya Smart Inc.                None
192.168.88.73   e8:94:f6:ba:c3:46 TP-LINK TECHNOLOGIES CO.,LTD.  None
192.168.88.31   80:af:ca:a8:e4:7f Shenzhen Cudy Technology Co., Ltd. 22/tcp,53/tcp,80/tcp
105.233.232.1   10:8f:fe:a9:74:c6 HUAWEI TECHNOLOGIES CO.,LTD    None
192.168.88.211  5e:af:57:e5:30:f4 Unknown                        None
192.168.88.130  b4:2e:99:ec:ca:43 GIGA-BYTE TECHNOLOGY CO.,LTD.  135/tcp,139/tcp,445/tcp
192.168.88.237  02:88:89:a7:7b:99 Unknown                        None
192.168.88.39   74:83:c2:33:ab:98 Ubiquiti Inc                   22/tcp
192.168.88.58   80:af:ca:22:27:f0 Shenzhen Cudy Technology Co., Ltd. 53/tcp,80/tcp,443/tcp
192.168.88.179  dc:a6:32:14:fe:4e Raspberry Pi Trading Ltd       139/tcp,445/tcp
192.168.88.38   0c:60:76:38:5e:ba Hon Hai Precision Ind. Co.,Ltd. None
192.168.88.178  10:5a:17:a8:d6:10 Tuya Smart Inc.                None
192.168.88.136  00:45:e2:f6:f8:9d CyberTAN Technology Inc.       None
192.168.88.76   80:af:ca:a8:e4:7f Shenzhen Cudy Technology Co., Ltd. 22/tcp,53/tcp,80/tcp
192.168.88.242  74:83:c2:33:b2:68 Ubiquiti Inc                   22/tcp
192.168.88.49   9e:79:c2:20:49:b7 Unknown                        49152/tcp
192.168.88.23   dc:a6:32:14:fe:4e Raspberry Pi Trading Ltd       139/tcp,445/tcp
192.168.88.51   c8:cd:55:e0:71:8a Ruijie Networks Co.,LTD        53/tcp,80/tcp
192.168.88.85   00:0b:82:7f:c0:59 Grandstream Networks, Inc.     22/tcp,80/tcp
192.168.88.226  d8:1f:12:2e:2f:bd Tuya Smart Inc.                None
192.168.88.171  d0:39:57:12:74:6d Liteon Technology Corporation  None
10.44.77.254    c8:cd:55:e0:71:8a Ruijie Networks Co.,LTD        None
192.168.88.32   7c:f6:66:75:8d:b0 Tuya Smart Inc.                None

LLDP Neighbors Summary Table:
Interface       Chassis ID        System Name                    Port Description
--------------- ----------------- ------------------------------ --------------------
eth2            74:83:c2:33:ab:98 Dias340ne                      eth0
eth2            b4:2e:99:ec:ca:43 Unknown                        Unknown
```

This output reveals a vibrant network with devices like Grandstream phones, Ubiquiti gear, Raspberry Pis, and more. The IP Neighbors Table shows which devices are active (e.g., open ports like 80/tcp for web servers or 22/tcp for SSH), while the LLDP table provides insight into directly connected devices, such as a system named `Dias340ne` on `eth0`.

## How the Script Works

The script is a Bash masterpiece that combines several Linux tools to paint a complete picture of your network:

1. **Dependency Checks**:
    
    * Ensures `curl`, `ip`, `nmap`, and `lldpcli` are installed.
        
    * If `lldpcli` is missing, it exits with instructions to install `lldpd` (e.g., `sudo apt install lldpd`).
        
    * Requires root privileges (use `sudo`) for `nmap` and `lldpcli`.
        
2. **IP Neighbors Table**:
    
    * Uses `ip neigh show | grep -v "::"` to list IPv4 neighbors from the ARP table, excluding IPv6 addresses (identified by `::`).
        
    * Queries [`https://api.macvendors.com/<MAC_ADDRESS>`](https://api.macvendors.com/%3CMAC_ADDRESS%3E) to get the vendor for each MAC address.
        
    * Runs `nmap -F --open -T4 <IP>` to scan ~100 common TCP ports and list open ones (e.g., `80/tcp,443/tcp`).
        
    * Formats the output into a table with columns: **IP Address**, **MAC Address**, **Vendor** (30 characters wide), and **Open Ports**.
        
3. **LLDP Neighbors Table**:
    
    * Runs `lldpcli show neighbors summary` to get LLDP neighbor details.
        
    * Parses the output to extract **Interface**, **Chassis ID** (full MAC address), **System Name**, and **Port Description**.
        
    * Handles missing fields (e.g., `Unknown` for missing System Name or Port Description).
        
    * Displays a formatted table, ensuring all neighbors are included.
        

## The Script

Here's the full script you can save and run:

```bash
#!/bin/bash

# Check if curl is installed
if ! command -v curl &> /dev/null; then
    echo "Error: curl is not installed. Please install it using 'sudo apt install curl' or equivalent."
    exit 1
fi

# Check if ip command is available
if ! command -v ip &> /dev/null; then
    echo "Error: ip command is not installed. Please install iproute2 using 'sudo apt install iproute2' or equivalent."
    exit 1
fi

# Check if nmap is installed
if ! command -v nmap &> /dev/null; then
    echo "Error: nmap is not installed. Please install it using 'sudo apt install nmap' or equivalent."
    exit 1
fi

# Check if lldpcli is installed
if ! command -v lldpcli &> /dev/null; then
    echo "Error: lldpcli is not installed. Please install it using 'sudo apt install lldpd' or equivalent."
    exit 1
fi

# Check if script is run as root (required for nmap and lldpcli)
if [[ $EUID -ne 0 ]]; then
    echo "Error: This script must be run as root for nmap and lldpcli to function."
    exit 1
fi

# Function to query MAC vendor
get_vendor() {
    local mac=$1
    # Query macvendors.com API and extract vendor name
    vendor=$(curl -s "https://api.macvendors.com/$mac")
    # Check if the response is empty or contains an error
    if [[ -z "$vendor" || "$vendor" == *"error"* ]]; then
        echo "Unknown"
    else
        # Crop vendor name to 30 characters
        echo "${vendor:0:30}"
    fi
}

# Function to get open ports using nmap
get_open_ports() {
    local ip=$1
    # Perform a quick TCP SYN scan on common ports (-F for fast scan)
    ports=$(nmap -F --open -T4 "$ip" | grep ^[0-9] | awk '{print $1}' | tr '\n' ',' | sed 's/,$//')
    if [[ -z "$ports" ]]; then
        echo "None"
    else
        echo "$ports"
    fi
}

# Print IP neighbors table header
echo "IP Neighbors Table:"
printf "%-15s %-17s %-30s %s\n" "IP Address" "MAC Address" "Vendor" "Open Ports"
printf "%-15s %-17s %-30s %s\n" "---------------" "-----------------" "------------------------------" "--------------------"

# Get IP neighbors, filter out IPv6 (lines containing ::), and process each entry
ip neigh show | grep -v "::" | while read -r line; do
    # Extract IP and MAC address using awk
    ip=$(echo "$line" | awk '{print $1}')
    mac=$(echo "$line" | awk '{print $5}')
    
    # Only process lines with valid IP and MAC addresses
    if [[ -n "$ip" && -n "$mac" ]]; then
        # Get vendor for the MAC address
        vendor=$(get_vendor "$mac")
        # Get open ports for the IP
        ports=$(get_open_ports "$ip")
        # Print formatted output
        printf "%-15s %-17s %-30s %s\n" "$ip" "$mac" "$vendor" "$ports"
    fi
done

# Print LLDP neighbors table
echo -e "\nLLDP Neighbors Summary Table:"
# Check if lldpcli command returns any neighbors
lldp_output=$(lldpcli show neighbors summary 2>/dev/null)
if [[ -z "$lldp_output" || $(echo "$lldp_output" | grep -c "Interface:") -eq 0 ]]; then
    echo "No LLDP neighbors found."
else
    # Print LLDP table header
    printf "%-15s %-17s %-30s %s\n" "Interface" "Chassis ID" "System Name" "Port Description"
    printf "%-15s %-17s %-30s %s\n" "---------------" "-----------------" "------------------------------" "--------------------"
    
    # Process lldpcli output
    echo "$lldp_output" | awk '
    BEGIN { interface=""; chassis=""; sysname="Unknown"; portdesc="Unknown"; }
    /Interface:/ { 
        if (interface != "") {
            printf "%-15s %-17s %-30s %s\n", interface, chassis, sysname, portdesc;
        }
        interface=$2; sub(/,$/, "", interface);
        chassis=""; sysname="Unknown"; portdesc="Unknown";
    }
    /ChassisID:/ { if ($3 == "mac") { chassis=$4 } else { chassis=$3 } }
    /SysName:/ { sysname=$2 }
    /PortDescr:/ { portdesc=$2 }
    END { if (interface != "") {
            printf "%-15s %-17s %-30s %s\n", interface, chassis, sysname, portdesc;
        }
    }'
fi

exit 0
```

## How to Use It

1. **Save the Script**:
    
    * Copy the script into a file, e.g., `network_discovery.sh`.
        
    * Make it executable:
        
        ```bash
        chmod +x network_discovery.sh
        ```
        
2. **Install Dependencies**:
    
    * Ensure `curl`, `iproute2`, `nmap`, and `lldpd` are installed. On Debian-based systems:
        
        ```bash
        sudo apt update
        sudo apt install curl iproute2 nmap lldpd
        ```
        
    * Start the `lldpd` daemon if not already running:
        
        ```bash
        sudo systemctl start lldpd
        ```
        
3. **Run the Script**:
    
    * Execute with root privileges:
        
        ```bash
        sudo ./network_discovery.sh
        ```
        
    * If the ARP table is empty, ping devices to populate it:
        
        ```bash
        ping 192.168.88.1
        ```
        

## Tips and Considerations

* **Root Privileges**: The script requires `sudo` for `nmap` (SYN scanning) and `lldpcli` (LLDP data access).
    
* **API Rate Limits**: The [`macvendors.com`](http://macvendors.com) API may have rate limits. If you get "Too many requests" errors, add a `sleep 1` in the `get_vendor` function or switch to an alternative API like [`https://api.maclookup.app/v2/macs/<MAC_ADDRESS>`](https://api.maclookup.app/v2/macs/%3CMAC_ADDRESS%3E).
    
* **Nmap Speed**: The `-F` flag scans ~100 common ports for speed. For a full scan, replace with `-p-` (all 65,535 ports, slower) or specify ports (e.g., `-p 1-1000`).
    
* **LLDP Requirements**: LLDP must be enabled on your network devices (e.g., switches, routers). If no LLDP neighbors appear, check if your devices support LLDP or if `lldpd` is running.
    
* **Firewalls**: Devices with firewalls may show "None" for open ports. Use `nmap --reason` for debugging.
    
* **Network Population**: If the IP Neighbors Table is empty, ping devices on your network to populate the ARP table.
    

## Why This Script Rocks

This script is a lekker way to get a quick, comprehensive view of your network. Whether you're troubleshooting connectivity, auditing for unauthorized devices, or just geeking out over your network setup, it provides:

* **Device Identification**: IP, MAC, and vendor details help you recognize devices (e.g., spotting that Raspberry Pi or Ubiquiti gear).
    
* **Service Discovery**: Open ports reveal what services devices are running (e.g., SSH on 22/tcp, web servers on 80/tcp).
    
* **Network Topology**: LLDP data shows direct connections, useful in enterprise environments with managed switches.
    

So, fire up your terminal, run the script, and get to know your network neighbors like never before! Got ideas for tweaks or want to add more features? Let me know in the comments!

---

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1761453482600/2a6fead0-440f-4262-a430-603cb948d8e0.avif align="center")

Ronald Bartels | [LinkedIn](https://www.linkedin.com/in/ronaldxbartels/) | [Instagram](https://www.instagram.com/ron_mastelek/)

---

[Nepean Networks](https://nepeannetworks.com)

[The Hub & Spoke | SD-WAN Blog](https://hubandspoke.amastelek.com/)

[The Morning Patrol with Ron Mastelek 💪](https://ron1821.substack.com/)
