英文:
Go : Raw winsock
问题
我正在尝试创建一个简单的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"
"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
}
这段代码中的问题是socket.Recvfrom
抛出了一个"不支持的套接字"错误。
英文:
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("\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
}
答案1
得分: 2
在当前版本的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
}
这是上面静态错误消息的返回值。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论