feat: scan for device IP and MAC, and helper function to optionally run code run the 'arp -a' command using os/exec to scan for devices (IP and MAC) also wrote a function which asks user if they would like to do something instead of just doing it, will eventually add flags to do this but this is a temporary workararound
Brijesh Wawdhane brijesh@wawdhane.com
Sat, 21 Sep 2024 15:21:20 +0530
3 files changed,
107 insertions(+),
7 deletions(-)
A
arp/arp.go
@@ -0,0 +1,48 @@
+package arp + +import ( + "fmt" + "os/exec" + "regexp" + "runtime" + "strings" +) + +type Device struct { + IP string + MAC string +} + +func GetDevices() ([]Device, error) { + if runtime.GOOS == "windows" { + return nil, fmt.Errorf("this program is not supported on Windows") + } + + cmd := exec.Command("arp", "-a") + output, err := cmd.Output() + if err != nil { + return nil, err + } + + return parseARPTable(string(output)), nil +} + +func parseARPTable(arpTable string) []Device { + var devices []Device + + pattern := regexp.MustCompile(`(\d+\.\d+\.\d+\.\d+).*?(\S+:\S+:\S+:\S+:\S+:\S+)`) + + lines := strings.Split(arpTable, "\n") + for _, line := range lines { + matches := pattern.FindStringSubmatch(line) + if len(matches) == 3 { + device := Device{ + IP: matches[1], + MAC: matches[2], + } + devices = append(devices, device) + } + } + + return devices +}
M
main.go
→
main.go
@@ -1,9 +1,11 @@
package main import ( + "fmt" "log" "os" + "network-scan/arp" "network-scan/database" "network-scan/oui" "network-scan/utils"@@ -38,12 +40,28 @@ utils.PrintInColor("Database opened successfully", 28)
} defer db.Close() - file, err := os.Open("standards-oui.ieee.org.txt") - if err != nil { - log.Fatalf("Error opening file: %v", err) - } - defer file.Close() + utils.ConfirmBeforeRunning("Do you want to seed sqlite from IEEE data?", func() { + file, err := os.Open("standards-oui.ieee.org.txt") + if err != nil { + log.Fatalf("Error opening file: %v", err) + } + defer file.Close() - oui.ScanDataFromTextFile("/Users/brijesh/projects/ongoing/network-scan/standards-oui.ieee.org.txt", db) - utils.PrintInColor("OUI data imported successfully", 28) + oui.ScanDataFromTextFile("/Users/brijesh/projects/ongoing/network-scan/standards-oui.ieee.org.txt", db) + utils.PrintInColor("OUI data imported successfully", 28) + }) + + utils.ConfirmBeforeRunning("Do you want to scan for devices in your network?", func() { + devices, err := arp.GetDevices() + if err != nil { + fmt.Println("Error:", err) + return + } + + fmt.Println("Devices found:") + for _, device := range devices { + fmt.Printf("IP: %s, MAC: %s\n", device.IP, device.MAC) + } + }) + }
A
utils/confirmation.go
@@ -0,0 +1,34 @@
+package utils + +import ( + "bufio" + "fmt" + "os" + "strings" +) + +func ConfirmBeforeRunning(prompt string, fn func()) { + reader := bufio.NewReader(os.Stdin) + + for { + fmt.Printf("%s (Y/n): ", prompt) + response, err := reader.ReadString('\n') + if err != nil { + fmt.Println("Error reading input:", err) + return + } + + response = strings.TrimSpace(strings.ToLower(response)) + + switch response { + case "y", "yes", "": + fn() + return + case "n", "no": + fmt.Println("Operation cancelled.") + return + default: + fmt.Println("Invalid response. Please answer with 'y' or 'n'.") + } + } +}