How can I get all addresses and masks from local interfaces in golang?
I need the actual network mask configured along with every IP address.
This code does not show the network masks in Windows 7:
package main
import (
"fmt"
"log"
"net"
)
func localAddresses() {
ifaces, err := net.Interfaces()
if err != nil {
log.Print(fmt.Errorf("localAddresses: %v\n", err.Error()))
return
}
for _, i := range ifaces {
addrs, err := i.Addrs()
if err != nil {
log.Print(fmt.Errorf("localAddresses: %v\n", err.Error()))
continue
}
for _, a := range addrs {
log.Printf("%v %v\n", i.Name, a)
}
}
}
func main() {
localAddresses()
}
UPDATE: This issue has been fixed in Go: https://github.com/golang/go/issues/5395
The configuration files for network interfaces are located in the /etc/sysconfig/network-scripts/ directory. The scripts used to activate and deactivate these network interfaces are also located here.
You won't "give both ports the same IP address" since there will only be one "port" visible to give an IP address to. Save this answer. Show activity on this post. Each "LAN port", or NIC, must have a unique IP address.
There are multiply types of addresses that a net.Interface
might have. The Addr
is just an interface which may contain a net.IPAddr
. But with a type assertion or type switch you can access the actual address type:
package main
import (
"fmt"
"net"
)
func localAddresses() {
ifaces, err := net.Interfaces()
if err != nil {
fmt.Print(fmt.Errorf("localAddresses: %+v\n", err.Error()))
return
}
for _, i := range ifaces {
addrs, err := i.Addrs()
if err != nil {
fmt.Print(fmt.Errorf("localAddresses: %+v\n", err.Error()))
continue
}
for _, a := range addrs {
switch v := a.(type) {
case *net.IPAddr:
fmt.Printf("%v : %s (%s)\n", i.Name, v, v.IP.DefaultMask())
}
}
}
}
func main() {
localAddresses()
}
Edit
Unfortunately the net
package doesn't return the Mask of the address. So, you will have to do the low level syscalls that the net
package does. The code below is an example, but parsing of the ip and the mask still needs to be done:
package main
import (
"fmt"
"net"
"os"
"syscall"
"unsafe"
)
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 localAddresses() error {
ifaces, err := net.Interfaces()
if err != nil {
return err
}
aList, err := getAdapterList()
if err != nil {
return err
}
for _, ifi := range ifaces {
for ai := aList; ai != nil; ai = ai.Next {
index := ai.Index
if ifi.Index == int(index) {
ipl := &ai.IpAddressList
for ; ipl != nil; ipl = ipl.Next {
fmt.Printf("%s: %s (%s)\n", ifi.Name, ipl.IpAddress, ipl.IpMask)
}
}
}
}
return err
}
func main() {
err := localAddresses()
if err != nil {
panic(err)
}
}
Some code shamelessly borrowed from interface_windows.go. Even comments are left intact
I'm modifying @ANisus answer and get all interfaces & masks (tested on Windows 10 & WSL in it (Microsoft Ubuntu 16.04.5 LTS):
package main
import (
"fmt"
"net"
)
func localAddresses() {
ifaces, err := net.Interfaces()
if err != nil {
fmt.Print(fmt.Errorf("localAddresses: %+v\n", err.Error()))
return
}
for _, i := range ifaces {
addrs, err := i.Addrs()
if err != nil {
fmt.Print(fmt.Errorf("localAddresses: %+v\n", err.Error()))
continue
}
for _, a := range addrs {
switch v := a.(type) {
case *net.IPAddr:
fmt.Printf("%v : %s (%s)\n", i.Name, v, v.IP.DefaultMask())
case *net.IPNet:
fmt.Printf("%v : %s [%v/%v]\n", i.Name, v, v.IP, v.Mask)
}
}
}
}
func main() {
localAddresses()
}
This should give you the ipnet
you're looking for.
ip, ipnet, err := net.ParseCIDR(a.String())
I know this post for Windows 7, but if you use Mac OS X hope this could help you.
Just Call GetNetMask("en0")
func GetNetMask(deviceName string) string {
switch runtime.GOOS {
case "darwin":
cmd := exec.Command("ipconfig", "getoption", deviceName, "subnet_mask")
out, err := cmd.CombinedOutput()
if err != nil {
return ""
}
nm := strings.Replace(string(out), "\n", "", -1)
log.Println("netmask=", nm, " OS=", runtime.GOOS)
return nm
default:
return ""
}
return ""
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With