英文:
sending ARP request by calling Windows DLLs inside Go doesn't work
问题
我正在尝试从Go语言中调用Windows API SendARP 来发送ARP请求,但它总是返回1168
,也就是ERROR_NOT_FOUND
,根据MSDN对这个错误代码的描述:
> 找不到元素。如果SrcIp参数未在本地计算机上的接口上指定源IPv4地址或指定了INADDR_ANY IP地址(IPv4地址为0.0.0.0),则在Windows Vista上返回此错误。
但我使用的是Windows 7,并且我确实指定了正确的源IPv4地址。在Wireshark中我也没有看到发送的ARP数据包。那么问题出在哪里呢?
package main
import (
"fmt"
"syscall"
"net"
"unsafe"
)
var (
iphlp, _ = syscall.LoadLibrary("iphlpapi.dll")
SendARP, _ = syscall.GetProcAddress(iphlp, "SendARP")
)
func sendARP(src, dst net.IP) {
//var nargs uintptr = 4
var len uint = 6
mac := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
ret, _, callErr := syscall.Syscall6(
uintptr(SendARP), 4,
uintptr(unsafe.Pointer(&dst[0])),
uintptr(unsafe.Pointer(&src[0])),
uintptr(unsafe.Pointer(&mac[0])),
uintptr(unsafe.Pointer(&len)),
0,
0)
if callErr == 0 {
fmt.Printf("result %v\n", int(ret))
}
}
func main() {
defer syscall.FreeLibrary(iphlp)
fmt.Printf("addr: %v\n", sendARP)
dst := net.IPv4(192,168,1,1)
src := net.IPv4(192,168,1,103)
sendARP(src, dst)
}
英文:
I'm trying to call a Windows API SendARP from Go to send arp request on Windows, but it always returns 1168
, AKA ERROR_NOT_FOUND
, description by MSDN on this error code:
> Element not found. This error is returned on Windows Vista if the the SrcIp parameter does not specify a source IPv4 address on an interface on the local computer or the INADDR_ANY IP address (an IPv4 address of 0.0.0.0).
but I'm on Windows 7, moreover I do specify a right source IPv4 address. And I see no ARP packet sent in Wireshark. So where is the problem?
package main
import (
"fmt"
"syscall"
"net"
"unsafe"
)
var (
iphlp, _ = syscall.LoadLibrary("iphlpapi.dll")
SendARP, _ = syscall.GetProcAddress(iphlp, "SendARP")
)
func sendARP(src, dst net.IP) {
//var nargs uintptr = 4
var len uint = 6
mac := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
ret, _, callErr := syscall.Syscall6(
uintptr(SendARP), 4,
uintptr(unsafe.Pointer(&dst[0])),
uintptr(unsafe.Pointer(&src[0])),
uintptr(unsafe.Pointer(&mac[0])),
uintptr(unsafe.Pointer(&len)),
0,
0)
if callErr == 0 {
fmt.Printf("result %v\n", int(ret))
}
}
func main() {
defer syscall.FreeLibrary(iphlp)
fmt.Printf("addr: %v\n", sendARP)
dst := net.IPv4(192,168,1,1)
src := net.IPv4(192,168,1,103)
sendARP(src, dst)
}
答案1
得分: 2
请尝试以下代码:
package main
import (
"fmt"
"log"
"net"
"syscall"
"unsafe"
)
var SendARP = syscall.MustLoadDLL("iphlpapi.dll").MustFindProc("SendARP")
func ip4ToUint32(ip net.IP) (uint32, error) {
ip = ip.To4()
if ip == nil {
return 0, fmt.Errorf("ip地址 %v 不是IPv4地址", ip)
}
var ret uint32
for i := 4; i > 0; i-- {
ret <<= 8
ret += uint32(ip[i-1])
}
return ret, nil
}
func sendARP(ip net.IP) (net.HardwareAddr, error) {
dst, err := ip4ToUint32(ip)
if err != nil {
return nil, err
}
mac := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
n := uint32(len(mac))
ret, _, _ := SendARP.Call(
uintptr(dst),
0,
uintptr(unsafe.Pointer(&mac[0])),
uintptr(unsafe.Pointer(&n)))
if ret != 0 {
return nil, syscall.Errno(ret)
}
return mac, nil
}
func main() {
ip := net.IPv4(192, 168, 1, 1)
mac, err := sendARP(ip)
if err != nil {
log.Fatalf("无法找到 %q 的MAC地址: %v", ip, err)
}
fmt.Printf("%v 的MAC地址是 %v\n", ip, mac)
}
这段代码对我有效。
Alex
英文:
Please, try this
package main
import (
"fmt"
"log"
"net"
"syscall"
"unsafe"
)
var SendARP = syscall.MustLoadDLL("iphlpapi.dll").MustFindProc("SendARP")
func ip4ToUint32(ip net.IP) (uint32, error) {
ip = ip.To4()
if ip == nil {
return 0, fmt.Errorf("ip address %v is not ip4", ip)
}
var ret uint32
for i := 4; i > 0; i-- {
ret <<= 8
ret += uint32(ip[i-1])
}
return ret, nil
}
func sendARP(ip net.IP) (net.HardwareAddr, error) {
dst, err := ip4ToUint32(ip)
if err != nil {
return nil, err
}
mac := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
n := uint32(len(mac))
ret, _, _ := SendARP.Call(
uintptr(dst),
0,
uintptr(unsafe.Pointer(&mac[0])),
uintptr(unsafe.Pointer(&n)))
if ret != 0 {
return nil, syscall.Errno(ret)
}
return mac, nil
}
func main() {
ip := net.IPv4(192, 168, 1, 1)
mac, err := sendARP(ip)
if err != nil {
log.Fatalf("could not find MAC for %q: %v", ip, err)
}
fmt.Printf("MAC address for %v is %v\n", ip, mac)
}
it works for me.
Alex
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论