猿问

使用原始套接字发送自定义以太网数据包

我搜索了如何使用自定义以太网类型发送原始以太网数据包,但很多人都在谈论 tcp 和 udp 协议。我需要打开一个原始套接字,获取所有具有我自定义以太网类型的数据包,读取有效负载并发送回具有不同自定义以太网类型的数据包。


func main() {

    //set promiscuos mode

    cmd := exec.Command("ifconfig", "eth0", "promisc")

    err := cmd.Run()

    if err != nil {

        fmt.Println("Error: " + err.Error())

        return

    }

    //open raw socket with custom ethertype_1 and bind to interface

    fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, Htons(ETHER_TYPE_1))

    if err != nil {

        fmt.Println("Error: " + err.Error())

        return

    }

    err = syscall.BindToDevice(fd, "eth0")

    if err != nil {

        fmt.Println("Error: " + err.Error())

        return

    }

    f := os.NewFile(uintptr(fd), fmt.Sprintf("fd %d", fd))


    for {

        buf := make([]byte, 1024)

        numRead, err := f.Read(buf)

        if err != nil {

            fmt.Println(err)

        }

        go ReadSocket(buf, numRead)

    }


func ReadSocket(buf []byte, numRead int) {

    packet := BufToEthPacket(buf, numRead)


    fmt.Printf("Destination MAC: % X\n", packet.dstMac)

    fmt.Printf("Source MAC:      % X\n", packet.srcMac)

    fmt.Printf("ether type:      %X\n", packet.ethType)

    fmt.Printf("Payload:         % X\n", packet.payload)


    var myPacket EthPacket

    myPacket.srcMac = packet.dstMac

    myPacket.dstMac = packet.srcMac

    myPacket.ethType = ETHER_TYPE_2

    myPacket.payload = packet.payload


    var myBuf = EthPacketToBuf(myPacket)


    //open raw socket with custom ethertype_2 and bind to interface

    fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, Htons(ETHER_TYPE_2))

    if err != nil {

        fmt.Println("Error: " + err.Error())

        return

    }

    err = syscall.BindToDevice(fd, "eth0")

    if err != nil {

        fmt.Println("Error: " + err.Error())

        return

    }

}

我收到了数据包,但f.Write(myBuf)返回以下错误:Error: write fd 5: no such device or address


我做错了什么?


哈士奇WWW
浏览 119回答 1
1回答

海绵宝宝撒

Usingos.Write将在后台执行write系统调用,这意味着实际文件。要将数据“写入”到网络套接字,您需要使用sendto系统调用。以下示例使用自定义以太类型发送数据。所以只是一个带有一些数据的以太网数据包。package mainimport (&nbsp; &nbsp; "log"&nbsp; &nbsp; "net"&nbsp; &nbsp; "os"&nbsp; &nbsp; "syscall")func main() {&nbsp; &nbsp; ifname := os.Args[1]&nbsp; &nbsp; iface, err := net.InterfaceByName(ifname)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal("get link by name:", err)&nbsp; &nbsp; }&nbsp; &nbsp; srcMac := iface.HardwareAddr&nbsp; &nbsp; if len(srcMac) == 0 {&nbsp; &nbsp; &nbsp; &nbsp; srcMac = []byte{0, 0, 0, 0, 0, 0}&nbsp; &nbsp; }&nbsp; &nbsp; dstMac := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}&nbsp; &nbsp; fd, _ := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(htons(syscall.ETH_P_ALL)))&nbsp; &nbsp; addr := syscall.SockaddrLinklayer{&nbsp; &nbsp; &nbsp; &nbsp; Ifindex: iface.Index,&nbsp; &nbsp; &nbsp; &nbsp; Halen:&nbsp; &nbsp;6, // Ethernet address length is 6 bytes&nbsp; &nbsp; &nbsp; &nbsp; Addr: [8]uint8{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dstMac[0],&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dstMac[1],&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dstMac[2],&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dstMac[3],&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dstMac[4],&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dstMac[5],&nbsp; &nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; }&nbsp; &nbsp; ethHeader := []byte{&nbsp; &nbsp; &nbsp; &nbsp; dstMac[0], dstMac[1], dstMac[2], dstMac[3], dstMac[4], dstMac[5],&nbsp; &nbsp; &nbsp; &nbsp; srcMac[0], srcMac[1], srcMac[2], srcMac[3], srcMac[4], srcMac[5],&nbsp; &nbsp; &nbsp; &nbsp; 0x12, 0x34, // your custom ethertype&nbsp; &nbsp; }&nbsp; &nbsp; // Your custom data&nbsp; &nbsp; p := append(ethHeader, []byte("Hello World")...)&nbsp; &nbsp; err = syscall.Sendto(fd, p, 0, &addr)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal("Sendto:", err)&nbsp; &nbsp; }}// htons converts a short (uint16) from host-to-network byte order.func htons(i uint16) uint16 {&nbsp; &nbsp; return (i<<8)&0xff00 | i>>8}
随时随地看视频慕课网APP

相关分类

Go
我要回答