Created
January 25, 2015 04:31
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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