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

时间:2014-05-07 22:34:34

标签: networking go ip ip-address

如何从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

中修复

4 个答案:

答案 0 :(得分:8)

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中无耻地借用了一些代码。甚至评论都保持不变

答案 1 :(得分:1)

这应该会为您提供您正在寻找的ipnet。

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

答案 2 :(得分:0)

我知道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 ""
}

答案 3 :(得分:0)

我正在修改@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()
}