package ifconfig
import (
"net"
"os"
"syscall"
"unsafe"
)
// NetLinkData contain network interface names + ip address
type NetLinkData struct {
Name string // interface name
IPNets []net.IPNet // ip v4 addresses
}
// Adapters Get List of network interfaces with ipv4 address
func Adapters() ([]NetLinkData, error) {
var awins []NetLinkData
ai, err := getAdapterList()
if err != nil {
return nil, err
}
for ; ai != nil; ai = ai.Next {
name := bytePtrToString(&ai.AdapterName[0])
awin := NetLinkData{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])
}
func bytePtrToString(p *uint8) string {
a := (*[10000]uint8)(unsafe.Pointer(p))
i := 0
for a[i] != 0 {
i++
}
return string(a[:i])
}
func getAdapterList() (*syscall.IpAdapterInfo, error) {
b := make([]byte, 1000)
l := uint32(len(b))
a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
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
}
// Getsysrange gets all system ipv4 ranges
func Getsysrange(apipa bool) (nets []string) {
ips, err := Adapters()
if err != nil {
return []string{"192.168.1.0/24"}
}
for _, i := range ips {
for _, j := range i.IPNets {
if !apipa && j.Contains(net.ParseIP("169.254.67.143")) {
continue
}
_, ipnetA, _ := net.ParseCIDR(j.String())
nets = append(nets, ipnetA.String())
}
}
return RemoveDuplicates(nets)
}
// RemoveDuplicates remove duplicates in slice of string
func RemoveDuplicates(elements []string) []string {
encountered := map[string]bool{}
result := []string{}
for v := range elements {
if encountered[elements[v]] == true {
} else {
encountered[elements[v]] = true
result = append(result, elements[v])
}
}
return result
}