jjzjj

windows - 转到 : Raw winsock

coder 2024-07-05 原文

我正在尝试创建一个简单的 tcp 原始 winsock,但我的 socket.Recvfrom 出现错误“不支持的套接字”,我做错了什么?

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("\nHost name : %s \n",hostname)

    //Retrieve the available IPs of the local host
    log.Println("Available Network Interfaces : \n")
    _ , 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
}

最佳答案

在当前版本的Go中,错误信息是

not supported by windows

这是不言自明的。

如果您跟踪对 Recvfrom() 的调用,您会发现

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

也就是上面静态错误信息的返回。

关于windows - 转到 : Raw winsock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42475093/

有关windows - 转到 : Raw winsock的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  3. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

    之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

  4. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  5. ruby - 如何在 Ruby 中执行 Windows CLI 命令? - 2

    我在目录“C:\DocumentsandSettings\test.exe”中有一个文件,但是当我用单引号编写命令时`C:\DocumentsandSettings\test.exe(我无法在此框中显示),用于在Ruby中执行命令,我无法这样做,我收到的错误是找不到文件或目录。我尝试用“//”和“\”替换“\”,但似乎没有任何效果。我也使用过系统、IO.popen和exec命令,但所有的努力都是徒劳的。exec命令还使程序退出,这是我不想发生的。提前致谢。 最佳答案 反引号环境就像双引号,所以反斜杠用于转义。此外,Ruby会将空格解

  6. ruby-on-rails - 我需要从 HTML 转到 markdown,有什么建议吗? - 2

    我正在使用Maruku,将Markdown(超集)转换为HTML,你知道我该怎么做才能从HTML转换为Markdown吗? 最佳答案 Google发现了一个名为reverse_markdown的ruby​​脚本.它似乎可以满足您的需求。 关于ruby-on-rails-我需要从HTML转到markdown,有什么建议吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/175162

  7. ruby - 错误 : Failed to build gem native extension on Windows - 2

    我在安装“redcarpet”gem时遇到以下错误。它在我friend的机器上安装没有问题。(我想安装它来运行yard)ruby版本:1.9.3命令输出:D:\Learning\Common_POM_FW\SampleProjects>yard[error]:Missing'redcarpet'gemforMarkdownformatting.Installitwith`geminstallredcarpet`D:\Learning\Common_POM_FW\SampleProjects>geminstallredcarpetTemporarilyenhancingPATHtoinc

  8. ruby - 从 Ruby 连接到适用于 Windows Phone 8 的 Microsoft 推送通知服务 - 2

    我们正在开发一个需要推送通知的WP8应用程序。为了测试它,我们使用CURL命令行运行推送通知POST请求,确保它实际连接,使用客户端SSL证书进行身份验证并发送正确的数据。我们确实知道,当我们收到对设备的推送时,这项工作是有效的。这是我们一直用于测试目的的CURL命令:curl--certclient_cert.pem-v-H"Content-Type:text/xml"-H"X-WindowsPhone-Target:Toast"-H"X-NotificationClass:2"-XPOST-d"MytitleMysubtitle"https://db3.notify.live.ne

  9. ruby - 在 Windows 7 上运行 Jekyll - 2

    我在Windows7上运行Jekyll时遇到问题。当我运行时jekyll出现以下错误C:\temp\jekyll\kouphax.github.com>jekyllConfigurationfromC:/temp/jekyll/kouphax.github.com/_config.ymlBuildingsite:C:/temp/jekyll/kouphax.github.com->C:/temp/jekyll/kouphax.github.com/_siteunit-testingYouaremissingalibraryrequiredforTextile.Pleaserun:$[s

  10. ruby - 是否有任何命令可以使用 vim 转到 Ruby block 的末尾(或开始) - 2

    有没有办法使用vim结束Rubyblock?例如moduleSomeModule#defsome_methodendend我想用一个命令从光标所在的位置移动到block的末尾,这可能吗?我读过thisdocumentation,但它似乎不适用于.rb文件,我在某些地方读到它只适用于C(虽然还没有尝试过)。提前致谢。 最佳答案 rubyforge好像有官方包对此有一些支持:TheRubyftpluginnowincludesRubyspecificimplementationsforthe[[,]],[],][,[m,]m,[M,an

随机推荐