Skip to content

Instantly share code, notes, and snippets.

@hnakamur
Created January 25, 2015 04:31
Show Gist options
  • Save hnakamur/a1bc4a46aca2defc9864 to your computer and use it in GitHub Desktop.
Save hnakamur/a1bc4a46aca2defc9864 to your computer and use it in GitHub Desktop.
List network interface names with pairs of IPv4 address and netmask on Windows using Go (MIT License)
package main
import (
"fmt"
"net"
"os"
"syscall"
"unsafe"
)
type AdapterWithIPNets struct {
Name string
IPNets []net.IPNet
}
func Adapters() ([]AdapterWithIPNets, error) {
var awins []AdapterWithIPNets
ai, err := getAdapterList()
if err != nil {
return nil, err
}
for ; ai != nil; ai = ai.Next {
name := bytePtrToString(&ai.AdapterName[0])
awin := AdapterWithIPNets{Name: name}
iai := &ai.IpAddressList
for ; iai != nil; iai = iai.Next {
ip := net.ParseIP(bytePtrToString(&iai.IpAddress.String[0]))
mask := parseIPv4Mask(bytePtrToString(&iai.IpMask.String[0]))
awin.IPNets = append(awin.IPNets, net.IPNet{IP: ip, Mask: mask})
}
awins = append(awins, awin)
}
return awins, nil
}
func parseIPv4Mask(ipStr string) net.IPMask {
ip := net.ParseIP(ipStr).To4()
return net.IPv4Mask(ip[0], ip[1], ip[2], ip[3])
}
// https://github.com/golang/go/blob/go1.4.1/src/net/interface_windows.go#L13-L20
func bytePtrToString(p *uint8) string {
a := (*[10000]uint8)(unsafe.Pointer(p))
i := 0
for a[i] != 0 {
i++
}
return string(a[:i])
}
// copied from https://github.com/golang/go/blob/go1.4.1/src/net/interface_windows.go#L22-L39
func getAdapterList() (*syscall.IpAdapterInfo, error) {
b := make([]byte, 1000)
l := uint32(len(b))
a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
// TODO(mikio): GetAdaptersInfo returns IP_ADAPTER_INFO that
// contains IPv4 address list only. We should use another API
// for fetching IPv6 stuff from the kernel.
err := syscall.GetAdaptersInfo(a, &l)
if err == syscall.ERROR_BUFFER_OVERFLOW {
b = make([]byte, l)
a = (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
err = syscall.GetAdaptersInfo(a, &l)
}
if err != nil {
return nil, os.NewSyscallError("GetAdaptersInfo", err)
}
return a, nil
}
func main() {
awins, err := Adapters()
if err != nil {
panic(err)
}
for _, awin := range awins {
fmt.Printf("name=%s\n", awin.Name)
for _, ipnet := range awin.IPNets {
fmt.Printf("addr=%s, mask=%s\n", ipnet.IP, ipnet.Mask)
}
fmt.Println()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment