82 lines
1.5 KiB
Go
82 lines
1.5 KiB
Go
package ping
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"os/exec"
|
|
"regexp"
|
|
"sync"
|
|
)
|
|
|
|
func PingLocal255() int {
|
|
localIP, err := getLocalIP()
|
|
if err != nil {
|
|
fmt.Println("Error getting local IP:", err)
|
|
return 0
|
|
}
|
|
|
|
network := getNetworkPrefix(localIP)
|
|
|
|
var wg sync.WaitGroup
|
|
deviceCount := 0
|
|
mu := &sync.Mutex{}
|
|
|
|
for i := 2; i < 255; i++ {
|
|
wg.Add(1)
|
|
go func(i int) {
|
|
defer wg.Done()
|
|
addr := fmt.Sprintf("%s.%d", network[:len(network)-2], i)
|
|
|
|
if addr == localIP.String() {
|
|
return
|
|
}
|
|
|
|
if ping(addr) {
|
|
mu.Lock()
|
|
deviceCount++
|
|
mu.Unlock()
|
|
}
|
|
}(i)
|
|
}
|
|
|
|
wg.Wait()
|
|
return deviceCount
|
|
}
|
|
|
|
func getLocalIP() (net.IP, error) {
|
|
addrs, err := net.InterfaceAddrs()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, addr := range addrs {
|
|
if ipnet, ok := addr.(*net.IPNet); ok && ipnet.IP.IsGlobalUnicast() {
|
|
return ipnet.IP, nil
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("local IP not found")
|
|
}
|
|
|
|
func getNetworkPrefix(ip net.IP) string {
|
|
ip = ip.To4()
|
|
return fmt.Sprintf("%d.%d.%d.0", ip[0], ip[1], ip[2])
|
|
}
|
|
|
|
func isValidIPv4(ip string) bool {
|
|
ipv4Regex := `^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$`
|
|
re := regexp.MustCompile(ipv4Regex)
|
|
return re.MatchString(ip)
|
|
}
|
|
|
|
func ping(ip string) bool {
|
|
if !isValidIPv4(ip) {
|
|
return false
|
|
}
|
|
output, err := exec.Command("ping", "-c", "1", "-W", "1", ip).CombinedOutput()
|
|
|
|
if err != nil {
|
|
return false
|
|
}
|
|
_ = output
|
|
return true
|
|
}
|