如何从本地接口获取所有地址和掩码?

Eve*_*ton 13 ip networking ip-address 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()
}
Run Code Online (Sandbox Code Playgroud)

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

ANi*_*sus 7

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()
}
Run Code Online (Sandbox Code Playgroud)

编辑

不幸的是,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)
    }
}
Run Code Online (Sandbox Code Playgroud)

一些代码无耻地从interface_windows.go中借用.甚至评论都保持不变

  • 查看`net`包的docs/source,我看到它们只提供IP.所以,你需要做的是使用`syscall`包.我会更新我的答案. (2认同)

AJI*_*IOB 7

我正在修改@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()
}
Run Code Online (Sandbox Code Playgroud)