如何在Go语言中获取本地接口的所有地址和掩码?

huangapple go评论76阅读模式
英文:

How to get all addresses and masks from local interfaces in go?

问题

如何在golang中获取本地接口的所有地址和掩码?

我需要获取每个IP地址的实际网络掩码。

以下代码在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()
}

更新:此问题已在Go中修复:https://github.com/golang/go/issues/5395

英文:

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

答案1

得分: 11

net.Interface可能具有多种类型的地址。Addr只是一个可能包含net.IPAddr的接口。但是通过类型断言或类型切换,您可以访问实际的地址类型:

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()
}

编辑

不幸的是,net包不返回地址的掩码。因此,您将不得不执行net包执行的低级系统调用。下面的代码是一个示例,但仍需要解析IP和掩码:

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)
	}
}

*一些代码无耻地从interface_windows.go中借用甚至注释都保留了*
英文:

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

答案2

得分: 9

我正在修改@ANisus的答案,并获取所有接口和掩码(在Windows 10和其中的WSL上进行了测试(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()
}
英文:

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()
}

答案3

得分: 3

这应该会给你所寻找的 ipnet

ip, ipnet, err := net.ParseCIDR(a.String())
英文:

This should give you the ipnet you're looking for.

ip, ipnet, err := net.ParseCIDR(a.String())

答案4

得分: 1

我知道这篇文章是关于Windows 7的,但如果你使用的是Mac OS X,希望这个可以帮到你。

只需调用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 ""
}
英文:

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 ""
}

huangapple
  • 本文由 发表于 2014年5月8日 06:34:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/23529663.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定