ZBLOG

go语言发送子网广播的arp请求报文,需要指定目标主机地址构造发送arp请求报文,之后如果接收到arp应答报文,则对比应答报文的源ip是否是指定的目标主机地址,是的话输出成功,否则输出失败

下面是 Go 语言发送子网广播的 ARP 请求报文并接收应答报文的示例代码:

”`go package main

import (

"fmt"
"net"

)

func main() {

// 构造目标 IP 地址和子网掩码
targetIP := net.IPv4(192, 168, 1, 255)
mask := net.IPMask(net.IPv4Mask(255, 255, 255, 0))

// 获取本机 IP 和 MAC 地址
localIP := getLocalIP(mask)
localMAC := getLocalMAC()

// 创建 ARP 请求包,并填充各字段值
arpPacket := &arpPacket{
    hardwareType:   []byte{0x00, 0x01}, // Ethernet
    protocolType:   []byte{0x08, 0x00}, // IPv4
    hardwareSize:   []byte{0x06},
    protocolSize:   []byte{0x04},
    opCode:         []byte{0x00, 0x01}, // ARP Request
    senderHardware: localMAC,
    senderProtocol: localIP.To4(),
    targetHardware: make([]byte, 6),
    targetProtocol: targetIP.To4(),
}

// 发送 ARP 请求报文到子网广播地址
conn, err := net.Dial("udp", fmt.Sprintf("%s:%d", targetIP.String(), arpPort))
if err != nil {
    panic(err)
}
defer conn.Close()

_, err = conn.Write(arpPacket.Marshal())
if err != nil {
	panic(err)
}

// 接收 ARP 应答报文,并解析各字段值
buffer := make([]byte, 1024)
conn.SetReadDeadline(time.Now().Add(arpTimeout))
n, _, err := conn.ReadFrom(buffer)
if err != nil {
	panic(err)
}
arpReplyPacket, err := parseARPPacket(buffer[:n])
if err != nil {
	panic(err)
}

// 对比应答报文的源 IP 是否是指定的目标主机地址
if arpReplyPacket.senderProtocol.String() == targetIP.String() {
	fmt.Println("ARP request succeeded!")
} else {
	fmt.Println("ARP request failed!")
}

}

type arpPacket struct {

hardwareType   []byte // 硬件类型,例如 Ethernet
protocolType   []byte // 协议类型,例如 IPv4
hardwareSize   []byte // 硬件地址长度
protocolSize   []byte // 协议地址长度
opCode         []byte // 操作码,例如 ARP Request 或 ARP Reply
senderHardware []byte // 发送方硬件地址,即本机 MAC 地址
senderProtocol net.IP // 发送方协议地址,即本机 IP 地址
targetHardware []byte // 目标硬件地址,通常为广播地址或某个 MAC 地址(仅在 ARP Reply 中使用)
targetProtocol net.IP // 目标协议地址,即欲查询的 IP 地址(仅在 ARP Request 中使用)

}

func (p *arpPacket) Marshal() []byte {

packetLen := 28 + len(p.hardwareSize) + len(p.protocolSize) + len(p.senderHardware) + len(p.senderProtocol) + len(p.targetHardware) + len(p.targetProtocol)
buffer := make([]byte, packetLen)

// 填充硬件类型和协议类型
copy(buffer[0:2], p.hardwareType)
copy(buffer[2:4], p.protocolType)

// 填充硬件地址长度和协议地址长度
copy(buffer[4:5], p.hardwareSize)
copy(buffer[5:6], p.protocolSize)

// 填充操作码、发送方 MAC 地址和 IP 地址、目标 MAC 地址和 IP 地址
copy(buffer[6:8], p.opCode)
offset := 8
copy(buffer[offset:], p.senderHardware)
offset += len(p.senderHardware)
copy(buffer[offset:], p.senderProtocol.To4())
offset += len(p.senderProtocol.To4())
copy(buffer[offset:], p.targetHardware)
offset += len(p.targetHardware)
copy(buffer[offset:], p.targetProtocol.To4())

return buffer

}

func parseARPPacket(data []byte) (*arpPacket, error) {

if len(data) < 28 {
	return nil, fmt.Errorf("invalid ARP packet")
}
packet := &arpPacket{
	hardwareType:   data[0:2],
	protocolType:   data[2:4],
	hardwareSize:   data[4:5],
	protocolSize:   data[5:6],
	opCode:         data[6:8],
    senderHardware: data[8:14],
    senderProtocol: net.IPv4(data[14], data[15], data[16], data[17]),
    targetHardware: data[18:24],
    targetProtocol: net.IPv4(data[24], data[25], data[26], data[27]),
}
return packet, nil

}

func getLocalIP(mask net.IPMask) net.IP {

addrs, err := net.InterfaceAddrs()
if err != nil {
    panic(err)
}
for _, addr := range addrs {
    ipnet, ok := addr.(*net.IPNet)
    if ok && !ipnet.IP.IsLoopback() && mask.Contains(ipnet.IP) {
        return ipnet.IP.Mask(mask)
    }
}
panic("no local IP address found")

}

func getLocalMAC() []byte {

ifas, err := net.Interfaces()
if err != nil {
    panic(err)
}
for _, ifa := range ifas {
    if ifa.Flags&net.FlagUp == 0 || ifa.Flags&net.FlagLoopback != 0 {
        continue
    }
    hwaddr := ifa.HardwareAddr
    if len(hwaddr) == 6 && hwaddr[0] != 0x00 && hwaddr[0] != 0xFF<br/><br/><br/><font size=1 color=#CCCCCC>内容由零声教学AI助手提供,问题来源于学员提问</font>

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

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

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

联系我们

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

微信号:3007537140

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

关注我们
x

注册

已经有帐号?