通过调用Go内部的Windows DLL发送ARP请求不起作用。

huangapple go评论135阅读模式
英文:

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数据包。那么问题出在哪里呢?

  1. package main
  2. import (
  3. "fmt"
  4. "syscall"
  5. "net"
  6. "unsafe"
  7. )
  8. var (
  9. iphlp, _ = syscall.LoadLibrary("iphlpapi.dll")
  10. SendARP, _ = syscall.GetProcAddress(iphlp, "SendARP")
  11. )
  12. func sendARP(src, dst net.IP) {
  13. //var nargs uintptr = 4
  14. var len uint = 6
  15. mac := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
  16. ret, _, callErr := syscall.Syscall6(
  17. uintptr(SendARP), 4,
  18. uintptr(unsafe.Pointer(&dst[0])),
  19. uintptr(unsafe.Pointer(&src[0])),
  20. uintptr(unsafe.Pointer(&mac[0])),
  21. uintptr(unsafe.Pointer(&len)),
  22. 0,
  23. 0)
  24. if callErr == 0 {
  25. fmt.Printf("result %v\n", int(ret))
  26. }
  27. }
  28. func main() {
  29. defer syscall.FreeLibrary(iphlp)
  30. fmt.Printf("addr: %v\n", sendARP)
  31. dst := net.IPv4(192,168,1,1)
  32. src := net.IPv4(192,168,1,103)
  33. sendARP(src, dst)
  34. }
英文:

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?

  1. package main
  2. import (
  3. "fmt"
  4. "syscall"
  5. "net"
  6. "unsafe"
  7. )
  8. var (
  9. iphlp, _ = syscall.LoadLibrary("iphlpapi.dll")
  10. SendARP, _ = syscall.GetProcAddress(iphlp, "SendARP")
  11. )
  12. func sendARP(src, dst net.IP) {
  13. //var nargs uintptr = 4
  14. var len uint = 6
  15. mac := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
  16. ret, _, callErr := syscall.Syscall6(
  17. uintptr(SendARP), 4,
  18. uintptr(unsafe.Pointer(&dst[0])),
  19. uintptr(unsafe.Pointer(&src[0])),
  20. uintptr(unsafe.Pointer(&mac[0])),
  21. uintptr(unsafe.Pointer(&len)),
  22. 0,
  23. 0)
  24. if callErr == 0 {
  25. fmt.Printf("result %v\n", int(ret))
  26. }
  27. }
  28. func main() {
  29. defer syscall.FreeLibrary(iphlp)
  30. fmt.Printf("addr: %v\n", sendARP)
  31. dst := net.IPv4(192,168,1,1)
  32. src := net.IPv4(192,168,1,103)
  33. sendARP(src, dst)
  34. }

答案1

得分: 2

请尝试以下代码:

  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net"
  6. "syscall"
  7. "unsafe"
  8. )
  9. var SendARP = syscall.MustLoadDLL("iphlpapi.dll").MustFindProc("SendARP")
  10. func ip4ToUint32(ip net.IP) (uint32, error) {
  11. ip = ip.To4()
  12. if ip == nil {
  13. return 0, fmt.Errorf("ip地址 %v 不是IPv4地址", ip)
  14. }
  15. var ret uint32
  16. for i := 4; i > 0; i-- {
  17. ret <<= 8
  18. ret += uint32(ip[i-1])
  19. }
  20. return ret, nil
  21. }
  22. func sendARP(ip net.IP) (net.HardwareAddr, error) {
  23. dst, err := ip4ToUint32(ip)
  24. if err != nil {
  25. return nil, err
  26. }
  27. mac := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
  28. n := uint32(len(mac))
  29. ret, _, _ := SendARP.Call(
  30. uintptr(dst),
  31. 0,
  32. uintptr(unsafe.Pointer(&mac[0])),
  33. uintptr(unsafe.Pointer(&n)))
  34. if ret != 0 {
  35. return nil, syscall.Errno(ret)
  36. }
  37. return mac, nil
  38. }
  39. func main() {
  40. ip := net.IPv4(192, 168, 1, 1)
  41. mac, err := sendARP(ip)
  42. if err != nil {
  43. log.Fatalf("无法找到 %q 的MAC地址: %v", ip, err)
  44. }
  45. fmt.Printf("%v 的MAC地址是 %v\n", ip, mac)
  46. }

这段代码对我有效。

Alex

英文:

Please, try this

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;log&quot;
  5. &quot;net&quot;
  6. &quot;syscall&quot;
  7. &quot;unsafe&quot;
  8. )
  9. var SendARP = syscall.MustLoadDLL(&quot;iphlpapi.dll&quot;).MustFindProc(&quot;SendARP&quot;)
  10. func ip4ToUint32(ip net.IP) (uint32, error) {
  11. ip = ip.To4()
  12. if ip == nil {
  13. return 0, fmt.Errorf(&quot;ip address %v is not ip4&quot;, ip)
  14. }
  15. var ret uint32
  16. for i := 4; i &gt; 0; i-- {
  17. ret &lt;&lt;= 8
  18. ret += uint32(ip[i-1])
  19. }
  20. return ret, nil
  21. }
  22. func sendARP(ip net.IP) (net.HardwareAddr, error) {
  23. dst, err := ip4ToUint32(ip)
  24. if err != nil {
  25. return nil, err
  26. }
  27. mac := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
  28. n := uint32(len(mac))
  29. ret, _, _ := SendARP.Call(
  30. uintptr(dst),
  31. 0,
  32. uintptr(unsafe.Pointer(&amp;mac[0])),
  33. uintptr(unsafe.Pointer(&amp;n)))
  34. if ret != 0 {
  35. return nil, syscall.Errno(ret)
  36. }
  37. return mac, nil
  38. }
  39. func main() {
  40. ip := net.IPv4(192, 168, 1, 1)
  41. mac, err := sendARP(ip)
  42. if err != nil {
  43. log.Fatalf(&quot;could not find MAC for %q: %v&quot;, ip, err)
  44. }
  45. fmt.Printf(&quot;MAC address for %v is %v\n&quot;, ip, mac)
  46. }

it works for me.

Alex

huangapple
  • 本文由 发表于 2017年4月16日 15:17:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/43434765.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定