ZBLOG

使用gopacket库实现一个程序,程序中开启一个协程广播发送指定目的IP的arp请求报文,每隔2s发送一次,共发送五次。另外一个协程持续监听arp应答报文,如果解析出应答 报文的源ip和指定的目的ip相同,则输出回包的源mac并结束程序

下面是使用gopacket库实现你描述的程序的一个示例:

package main

import (
	"fmt"
	"log"
	"net"
	"sync"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
)

var (
	srcIP        = net.IP{192, 168, 1, 100} // 源IP地址
	dstIP        = net.IP{192, 168, 1, 200} // 目标IP地址
	dstMAC       net.HardwareAddr           // 目标MAC地址(待解析)
	wg           sync.WaitGroup             // 等待协程结束的同步对象
	maxSendCount = 5                        // 最大发送次数
	sendInterval = time.Second * 2          // 发送间隔时间
)

func main() {
	go sendARPRequest()
	go listenARPReply()

	wg.Add(1)
	wg.Wait()
}

// 发送ARP请求报文
func sendARPRequest() {
	defer wg.Done()

	handle, err := gopacket.OpenLive("eth0", 65536, true, time.Second*5)
	if err != nil {
		log.Fatal(err)
	}
	defer handle.Close()

	for i := 0; i < maxSendCount; i++ {
		ethLayer := &layers.Ethernet{
			SrcMAC:       handle.LinkLayer().LinkSrc(),
			DstMAC:       layers.EthernetBroadcast,
			EthernetType: layers.EthernetTypeARP,
		}

		arplayer := &layers.ARP{
			AddrType:          layers.LinkTypeEthernet,
			Protocol:          layers.EthernetTypeIPv4,
			HwAddressSize:     uint8(len(handle.LinkLayer().LinkDst())),
			ProtAddressSize:   uint8(len(dstIP)),
			Operation:         layers.ARPRequest,
			SourceHwAddress:   handle.LinkLayer().LinkSrc(),
			SourceProtAddress: srcIP,
			DstHwAddress:      layers.EthernetBroadcast,
			DstProtAddress:    dstIP,
		}

		buffer := gopacket.NewSerializeBuffer()
		opts := gopacket.SerializeOptions{
			FixLengths:       true,
			ComputeChecksums: true,
		}
		err = gopacket.SerializeLayers(buffer, opts, ethLayer, arplayer)
		if err != nil {
			log.Fatal(err)
		}

		outgoingPacket := buffer.Bytes()
		err = handle.WritePacketData(outgoingPacket)
		if err != nil {
			log.Fatal(err)
		}

        // 输出发送的ARP请求报文信息
        fmt.Println("Sent ARP request:")
        fmt.Printf("Source MAC: %s\n", ethLayer.SrcMAC)
        fmt.Printf("Destination MAC: %s\n", ethLayer.DstMAC)
        fmt.Printf("Source IP: %s\n", arplayer.SourceProtAddress)
        fmt.Printf("Destination IP (Target): %s\n", arplayer.DstProtAddress)

        time.Sleep(sendInterval)
    }
}

// 监听ARP应答报文
func listenARPReply() {
	defer wg.Done()

	handle, err := gopacket.OpenLive("eth0", 65536, true, time.Second*5)
	if err != nil {
	    log.Fatal(err)
    }
    defer handle.Close()

    packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
	for packet := range packetSource.Packets() {
	    arpLayer := packet.Layer(layers.LayerTypeARP).(*layers.ARP)

	    // 解析出应答报文的源IP和目标IP
	    sourceIP := net.IP(arpLayer.SourceProtAddress)
	    targetIP := net.IP(arpLayer.DstProtAddress)

	    if sourceIP.Equal(dstIP) && targetIP.Equal(srcIP) {
	        // 输出回包的源MAC并结束程序
	        fmt.Println("Received ARP reply:")
	        fmt.Printf("Source IP: %s\n", arpLayer.SourceProtAddress)
	        fmt.Printf("Source MAC: %s\n", arpLayer.SourceHwAddress)

	        wg.Done()
	        break
        }
    }
}

请注意,上述代码中需要根据实际情况修改网络接口名称(如”eth0”)以及设置正确的网卡地址。此外,你可能需要使用管理员权限来运行该程序。

希望以上示例能够帮助你实现所需功能。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=1641

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?