duannan4486 2017-02-26 22:37
浏览 31
已采纳

前进:未加工的winsock

Am trying to create a simple tcp raw winsock but my socket.Recvfrom trows an error "Not supported socket", what am i doing wrong ?

package main

import (
    "golang.org/x/sys/windows"
    "github.com/google/gopacket"
    "github.com/google/gopacket/layers"
    "log"
    "net"
    "sync"
    "os"
    //~ "syscall"
    "time"
    "fmt"
    "errors"
    "unsafe"
)

const SIO_RCVALL = windows.IOC_IN | windows.IOC_VENDOR | 1

type Handle struct {
    blockForever bool
    device       string
    deviceIndex  int
    mu           sync.Mutex
    socket       windows.Handle
    timeout      time.Duration
    snaplen      int32
}

const BlockForever = -time.Millisecond * 10

func main() {
    var (
        device    string        = "eth0"
        Snaplen int32         = 65536
        Timeout     time.Duration = 30 * time.Second
    )

    var (
       ip4 layers.IPv4
       tcp layers.TCP
    )

    parser := gopacket.NewDecodingLayerParser(layers.LayerTypeIPv4, &ip4, &tcp)
    decoded := []gopacket.LayerType{}

    hnd, err := OpenLive(device, Snaplen, Timeout)
    if err != nil {
        log.Fatal(err)
    }
    defer hnd.Close()

    packetSource := gopacket.NewPacketSource(hnd, hnd.LinkType())

    for packetData := range packetSource.Packets() {
        err := parser.DecodeLayers(packetData.Data(), &decoded)

        if packetData == nil || err != nil {
            continue
        }

        for _, layerType := range decoded {
          switch layerType {
            case layers.LayerTypeIPv4:
                log.Println("    IP4 ", ip4.SrcIP, ip4.DstIP)
            case layers.LayerTypeTCP:
                log.Println(tcp.TransportFlow().Src().String())
          }
        }
  }

}

func OpenLive(device string, snaplen int32, timeout time.Duration) (handle *Handle, err error) {
    p := &Handle{}
    p.blockForever = timeout < 0
    p.timeout = timeout
    p.snaplen = snaplen

    var d windows.WSAData

    log.Println("Initialising Winsock...")
    err = windows.WSAStartup(uint32(0x202), &d)
    if err != nil {
        return nil, fmt.Errorf("Error: WSAStartup - %v", err)
    }
    log.Println("Initialised")

    //Create a RAW Socket
    log.Println("Creating RAW Socket...");
    fd, err := windows.Socket(windows.AF_INET, windows.SOCK_RAW, windows.IPPROTO_IP)
    if err != nil {
        return nil, fmt.Errorf("Error: socket - %v", err)
    }
    p.socket = fd
    log.Println("Created.")

    // Retrieve the local hostname
    hostname, err := os.Hostname()

    if err != nil {
        return nil, fmt.Errorf("Error: Hostname() - %v", err)
    }
    log.Printf("
Host name : %s 
",hostname)

    //Retrieve the available IPs of the local host
    log.Println("Available Network Interfaces : 
")
    _ , err = windows.GetHostByName(hostname)

    if err != nil {
        return nil, fmt.Errorf("Error: GetHostByName() - %v", err)
    }

    ip4 , iFcindex, err := externalIP()
    if err != nil {
        return nil, fmt.Errorf("Error: getIpv4() - %v", err)
    } 
    p.deviceIndex = iFcindex

    la := new(windows.SockaddrInet4)
    la.Port = int(0)

    for i := 0; i < net.IPv4len; i++ {
        la.Addr[i] = ip4[i]
    }

    if err := windows.Bind(fd, la); err != nil {
        return nil, fmt.Errorf ("Error:Bind - %v", err)
    }

    inbuf := uint32(1)
    sizebuf := uint32(unsafe.Sizeof(inbuf))
    ret := uint32(0)

    err = windows.WSAIoctl(fd, SIO_RCVALL , (*byte)(unsafe.Pointer(&inbuf)) ,sizebuf, nil ,0 ,&ret , nil, 0); 

    if err != nil {
        return nil, fmt.Errorf ("Error:WSAIoctl() failed - %v", err)
    }

    return p, nil

}

// Close closes the underlying socket handle.
func (p *Handle) Close() {
    p.mu.Lock()
    defer p.mu.Unlock()

    windows.Close(p.socket)
}

func (p *Handle) ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) {
    p.mu.Lock()
    data = make([]byte, 65536)
    n, _, err := windows.Recvfrom(p.socket, data, 0)
    log.Println(n)
    if err != nil {
        log.Printf("Error:Recvfrom() - %v", err)
    }
    ci = gopacket.CaptureInfo{Timestamp: time.Now(), CaptureLength: len(data), Length: n, InterfaceIndex: p.deviceIndex}

    p.mu.Unlock()

    return
}

func htons(n int) int {
    return int(int16(byte(n))<<8 | int16(byte(n>>8)))
}

func externalIP() (IPBYTE []byte, ifaceIndex int ,err error) {

    ifaces, err := net.Interfaces()
    if err != nil {
        return 
    }

    IPBYTE = make([]byte, 4)
    ifaceIndex =  0

    for _, iface := range ifaces {
        if iface.Flags&net.FlagUp == 0 {
            continue // interface down
        }
        if iface.Flags&net.FlagLoopback != 0 {
            continue // loopback interface
        }
        addrs, err := iface.Addrs()
        if err != nil {
            continue 
        }

        for _, addr := range addrs {
            var ip net.IP
            switch v := addr.(type) {
            case *net.IPNet:
                ip = v.IP
            case *net.IPAddr:
                ip = v.IP
            }
            if ip == nil || ip.IsLoopback() {
                continue
            }
            IPBYTE = ip.To4()
            ifaceIndex = iface.Index
            if IPBYTE == nil {
                continue // not an ipv4 address
            }
            //~ err = nil

            log.Printf("Active Network Interfaces %v : %v " ,iface.Index , ip.String())
            return IPBYTE ,ifaceIndex ,  nil 
        }
    }

    err = errors.New("are you connected to the network?")
    return 
}

// LinkType returns pcap_datalink, as a layers.LinkType.
func (p *Handle) LinkType() layers.LinkType {
    return layers.LinkTypeIPv4
}
  • 写回答

1条回答 默认 最新

  • doumeng3080 2017-02-27 10:36
    关注

    In the current version of Go, the error message is

    not supported by windows

    which is self-explanatory.

    If you follow your call to Recvfrom(), you will find

    func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) {
        return 0, nil, syscall.EWINDOWS
    }
    

    which is the return of a static error message above.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 winform的chart曲线生成时有凸起
  • ¥15 msix packaging tool打包问题
  • ¥15 finalshell节点的搭建代码和那个端口代码教程
  • ¥15 用hfss做微带贴片阵列天线的时候分析设置有问题
  • ¥15 Centos / PETSc / PETGEM
  • ¥15 centos7.9 IPv6端口telnet和端口监控问题
  • ¥120 计算机网络的新校区组网设计
  • ¥20 完全没有学习过GAN,看了CSDN的一篇文章,里面有代码但是完全不知道如何操作
  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 海浪数据 南海地区海况数据,波浪数据