lan_windows.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // Copyright (C) 2015 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at http://mozilla.org/MPL/2.0/.
  6. // +build windows
  7. package osutil
  8. import (
  9. "net"
  10. "os"
  11. "strings"
  12. "syscall"
  13. "unsafe"
  14. )
  15. // Modified version of:
  16. // http://stackoverflow.com/questions/23529663/how-to-get-all-addresses-and-masks-from-local-interfaces-in-go
  17. // v4 only!
  18. func getAdapterList() (*syscall.IpAdapterInfo, error) {
  19. b := make([]byte, 10240)
  20. l := uint32(len(b))
  21. a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
  22. // TODO(mikio): GetAdaptersInfo returns IP_ADAPTER_INFO that
  23. // contains IPv4 address list only. We should use another API
  24. // for fetching IPv6 stuff from the kernel.
  25. err := syscall.GetAdaptersInfo(a, &l)
  26. if err == syscall.ERROR_BUFFER_OVERFLOW {
  27. b = make([]byte, l)
  28. a = (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
  29. err = syscall.GetAdaptersInfo(a, &l)
  30. }
  31. if err != nil {
  32. return nil, os.NewSyscallError("GetAdaptersInfo", err)
  33. }
  34. return a, nil
  35. }
  36. func GetLans() ([]*net.IPNet, error) {
  37. ifaces, err := net.Interfaces()
  38. if err != nil {
  39. return nil, err
  40. }
  41. nets := make([]*net.IPNet, 0, len(ifaces))
  42. aList, err := getAdapterList()
  43. if err != nil {
  44. return nil, err
  45. }
  46. for _, ifi := range ifaces {
  47. for ai := aList; ai != nil; ai = ai.Next {
  48. index := ai.Index
  49. if ifi.Index == int(index) {
  50. ipl := &ai.IpAddressList
  51. for ; ipl != nil; ipl = ipl.Next {
  52. ipStr := strings.Trim(string(ipl.IpAddress.String[:]), "\x00")
  53. maskStr := strings.Trim(string(ipl.IpMask.String[:]), "\x00")
  54. ip := net.ParseIP(ipStr)
  55. maskip := net.ParseIP(maskStr)
  56. if ip.IsUnspecified() || maskip.IsUnspecified() {
  57. continue
  58. }
  59. nets = append(nets, &net.IPNet{
  60. IP: ip,
  61. Mask: net.IPv4Mask(
  62. maskip[net.IPv6len-net.IPv4len],
  63. maskip[net.IPv6len-net.IPv4len+1],
  64. maskip[net.IPv6len-net.IPv4len+2],
  65. maskip[net.IPv6len-net.IPv4len+3],
  66. ),
  67. })
  68. }
  69. }
  70. }
  71. }
  72. return nets, err
  73. }