-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSwiftPing.sh
More file actions
125 lines (105 loc) · 4.69 KB
/
SwiftPing.sh
File metadata and controls
125 lines (105 loc) · 4.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/bin/bash
# Enable strict mode for robust error handling. This will:
# - exit immediately if a command exits with a non-zero status (-e)
# - treat unset variables as an error (-u)
# - ensure the return value of a pipeline is the status of the last command
# to exit with a non-zero status, or zero if all commands exit successfully (-o pipefail)
set -euo pipefail
# Function to display usage instructions for the script.
display_usage() {
echo "Usage: ./SwiftPing.sh <IP_PREFIX> [START_OCTET] [END_OCTET]"
echo "Example 1 (full /24 subnet): ./SwiftPing.sh 192.168.1"
echo "Example 2 (custom range): ./SwiftPing.sh 192.168.1 10 50"
echo ""
echo "Note: Hostname resolution requires 'dig' command to be installed."
}
# Function to check if required commands (ping, dig) are installed on the system.
check_dependencies() {
local missing_commands=""
# Check for 'ping'
if ! command -v ping &>/dev/null; then
missing_commands+="ping "
fi
# If any commands are missing, print an error and exit.
if [ -n "$missing_commands" ]; then
echo "Error: The following required commands are not installed: $missing_commands"
echo "Please install them and try again."
exit 1
fi
}
# --- Main Script Logic Starts Here ---
# Run dependency checks before proceeding.
check_dependencies
# Check for the correct number of arguments provided by the user.
# The script expects 1 argument (IP_PREFIX) or 3 arguments (IP_PREFIX, START_OCTET, END_OCTET).
if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then
display_usage # Show usage if arguments are incorrect.
exit 1
fi
IP_PREFIX="$1" # Assign the first argument as the IP network prefix.
START_OCTET=1 # Default starting IP octet.
END_OCTET=254 # Default ending IP octet.
# If 3 arguments are provided, use them for a custom IP range.
if [ "$#" -eq 3 ]; then
START_OCTET="$2" # Assign the second argument as the custom start octet.
END_OCTET="$3" # Assign the third argument as the custom end octet.
# Validate that START_OCTET and END_OCTET are numeric.
if ! [[ "$START_OCTET" =~ ^[0-9]+$ && "$END_OCTET" =~ ^[0-9]+$ ]]; then
echo "Error: START_OCTET and END_OCTET must be numbers."
display_usage
exit 1
fi
# Validate that START_OCTET and END_OCTET are within a valid range (1-254).
if [ "$START_OCTET" -lt 1 ] || [ "$START_OCTET" -gt 254 ] || \
[ "$END_OCTET" -lt 1 ] || [ "$END_OCTET" -gt 254 ]; then
echo "Error: START_OCTET and END_OCTET must be between 1 and 254 (inclusive)."
display_usage
exit 1
fi
# Validate that START_OCTET is not greater than END_OCTET.
if [ "$START_OCTET" -gt "$END_OCTET" ]; then
echo "Error: START_OCTET cannot be greater than END_OCTET."
display_usage
exit 1
fi
fi
echo "Scanning $IP_PREFIX.$START_OCTET to $IP_PREFIX.$END_OCTET..."
echo "Active hosts found:"
echo "-------------------"
# Array to store Process IDs (PIDs) of background 'ping' operations.
PIDS=()
# Loop through each IP address in the specified range.
for ip in $(seq "$START_OCTET" "$END_OCTET"); do
# Run the ping and resolution logic in a subshell in the background.
# This allows for parallel scanning.
(
TARGET_IP="$IP_PREFIX.$ip"
# Perform a single ping with a 1-second timeout.
# Redirect stdout and stderr to /dev/null to keep the console clean.
if ping -c 1 -W 1 "$TARGET_IP" &>/dev/null; then
HOSTNAME="" # Initialize hostname to empty.
# Attempt hostname resolution only if 'dig' command is available.
if command -v dig &>/dev/null; then
# Use 'dig -x' for reverse DNS lookup and 'head -n 1' to get only the first result.
HOSTNAME=$(dig -x "$TARGET_IP" +short | head -n 1)
fi
# Print the result using printf to ensure a newline after each entry.
# If a hostname is found, print it in parentheses; otherwise, just print the IP.
if [ -n "$HOSTNAME" ]; then
printf "%s (%s)\n" "$TARGET_IP" "$HOSTNAME"
else
printf "%s\n" "$TARGET_IP"
fi
fi
) & # Run the entire subshell block in the background.
PIDS+=($!) # Add the PID of the background process to the array.
done
# Wait for all background 'ping' processes to complete.
# '|| true' is added to prevent 'set -e' from exiting the script if a background process
# finishes with a non-zero exit status (e.g., if a ping fails, but we don't want to halt the entire scan).
for pid in "${PIDS[@]}"; do
wait "$pid" || true
done
echo "-------------------"
echo "Scan complete."
echo "Note: Some hostnames might not resolve if 'dig' is not installed or available."