-
-
Save Oleksii909/3e01e8d6f34318c5beaba44d40def694 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mac | |
import ( | |
"context" | |
"fmt" | |
"log" | |
"network-chesswork/utilities" | |
"os" | |
"os/signal" | |
"sync" | |
"syscall" | |
"time" | |
"github.com/google/gopacket" | |
"github.com/google/gopacket/layers" | |
"github.com/google/gopacket/pcap" | |
) | |
const ( | |
snapLen = 1600 | |
promiscuous = true | |
timeout = pcap.BlockForever | |
sourcePath = "./temp/source-mac.json" | |
destPath = "./temp/dest-mac.json" | |
) | |
func Sniff(ctx context.Context, iface string) error { | |
if iface == "" { | |
return fmt.Errorf("network interface is required") | |
} | |
log.Printf("Sniffing package received interface: %s", iface) | |
// Open the network interface for packet capture | |
handle, err := pcap.OpenLive(iface, snapLen, promiscuous, timeout) | |
if err != nil { | |
return fmt.Errorf("failed to open live capture: %w", err) | |
} | |
defer handle.Close() | |
packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) | |
macAddresses := sync.Map{} | |
// Create a channel to receive OS signals | |
sigChan := make(chan os.Signal, 1) | |
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) | |
// Use a WaitGroup to wait for all goroutines to finish | |
var wg sync.WaitGroup | |
wg.Add(1) | |
go func() { | |
defer wg.Done() | |
for { | |
select { | |
case <-ctx.Done(): | |
return | |
case <-sigChan: | |
log.Println("Received termination signal. Stopping packet capture...") | |
return | |
case packet := <-packetSource.Packets(): | |
processPacket(packet, &macAddresses) | |
} | |
} | |
}() | |
wg.Wait() | |
return nil | |
} | |
func processPacket(packet gopacket.Packet, macAddresses *sync.Map) { | |
ethernetLayer := packet.Layer(layers.LayerTypeEthernet) | |
if ethernetLayer == nil { | |
return | |
} | |
ethernetPacket, ok := ethernetLayer.(*layers.Ethernet) | |
if !ok { | |
return | |
} | |
processMAC(ethernetPacket.SrcMAC.String(), sourcePath, macAddresses) | |
processMAC(ethernetPacket.DstMAC.String(), destPath, macAddresses) | |
} | |
func processMAC(mac, path string, macAddresses *sync.Map) { | |
if _, loaded := macAddresses.LoadOrStore(mac, true); !loaded { | |
log.Printf("New MAC Address: %s", mac) | |
data := map[string]interface{}{ | |
mac: map[string]interface{}{ | |
"time": time.Now().UTC().Format(time.RFC3339), | |
}, | |
} | |
if err := utilities.AppendJSON(path, data); err != nil { | |
log.Printf("Failed to append MAC address to JSON: %v", err) | |
} | |
} | |
} | |
// To use this enhanced version, you'll need to pass a context when calling the Sniff function: | |
ctx, cancel := context.WithCancel(context.Background()) | |
defer cancel() | |
err := mac.Sniff(ctx, "your_interface_name") | |
if err != nil { | |
log.Fatalf("Error while sniffing: %v", err) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment