Go语言如何获取网卡信息
目录
- net
- 网络接口
- 函数
- 类型
- syscall
- 网络接口
- github.com/google/gopacket/pcap
- 网络接口
- 函数
- 类型
- 处理网络流
- 函数
- 获取网卡信息的各种方法测试
- 问题
- 总结
net
网络接口
函数
func Interfaces() ([]Interface, error) {}
- 返回系统网络接口的列表
func InterfaceAddrs() ([]Addr, error) {}
- 返回一个系统单播接口地址的列表
- 该列表无法标识关联的接口
- 用Interfaces和Interface.Addrs获取更详细信息
func InterfaceByIndex(index int) (*Interface, error) {}
- 返回索引对应的接口
func InterfaceByName(name string) (*Interface, error) {}
- 返回名字对应的接口
类型
Interface
包含:索引(Index),MTU,名字(Name),硬件地址(HardwareAddr),标志位(up | broadcast | multicast)信息
Windows下的例子:
{Index:13 MTU:1500 Name:以太网 HardwareAddr:b8:85:84:bb:6a:36 Flags:up|broadcast|multicast}{Index:1 MTU:-1 Name:Loopback Pseudo-Interface 1 HardwareAddr: Flags:up|loopback|multicast}
type Interface struct { Index int // positive integer that starts at one, zero is never used MTU int // maximum transmission unit Name string // e.g., "en0", "lo0", "eth0.100" HardwareAddr HardwareAddr // IEEE MAC-48, EUI-48 and EUI-64 form Flags Flags // e.g., FlagUp, FlagLoopback, FlagMulticast }
- Addr
- 代表一个网络端点地址
示例:
String()
:“192.0.2.1:25”, “[2001:db8::1]:80&http://www.devze.comrdquo;, “127.0.0.1/8”Network()
:“tcp”, “udp”, “ip+net”
type Addr interface { Network() string // name of the network (for example, "tcp", "udp", "ip+net") String() string // string form of address (for example, ) }
syscall
网络接口
原本是go 1.5之前interface_windows.go下的源码,后来被移除了。
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 }
getAdapterList()
返回一个*syscall.IpAdapterInfo编程客栈链表,通过Next指向下一个网卡。
字段名 | 解释 | 类型 | 示例 |
---|---|---|---|
Index | 索引 | uint32 | 13 |
AdapterName | 适配器ID | []uint8 | {5C9384EF-DEBA-43A6-AE6A-5D10C952C481} |
Description | 描述 | []uint8 | Intel® Ethernet Connection (7) I219-LM |
DhcpEnabled | DHCP状态 | uint32 | 1 |
IpAddressList | ip链表 | syscall.IpAddrString | {IpAddress:“192.168.13.31”, IpMask:“255.255.255.0”} |
GatewayList | 网关链表 | syscall.IpAddrString | {IpAddress:“192.168.13.1”, IpMask:“255.255.255.255”} |
DhcpServer | DHCP服务器链表 | syscall.IpAddrString | {IpAddress:“192.168.13.254”, IpMask:“255.255.255.255”} |
type IpAdapterInfo struct { Next *IpAdapterInfo ComboIndex uint32 AdapterName [MAX_ADAPTER_NAME_LENGTH + 4]byte Description [MAX_ADAPTER_DESCRIPTION_LENGTH + 4]byte AddressLength uint32 Address [MAX_ADAPTER_ADDRESS_LENGTH]byte Index uint32 Type uint32 DhcpEnabled uint32 CurrentIpAddress *IpAddrString IpAddressList IpAddrString GatewayList IpAddrString DhcpServer IpAddrString HaveWins bool PrimaryWinsServer IpAddrString SecondaryWinsServer IpAddrString Leaseobtained int64 LeaseExpires int64 }
github.com/google/gopacket/pcap
网络接口
函数
func FindAllDevs() (ifs []Interface, err error) {}
- 返回
Interface
列表
类型
Interface
- 描述了机器上一个单独的网络接口
- 包含:名字(Name),描述,标志位,地址(
InterfaceAddress
列表)信息
示例:
type Interface struct { Name string Description string Flagsjs uint32 Addrhttp://www.devze.comesses []InterfaceAddress } type InterfaceAddress struct { IP net.IP Netmask net.IPMask // Netmask may be nil if we were unable to retrieve it. Broadaddr net.IP // Broadcast address for this IP may be nil P2P net.IP // P2P destination address for this IP may be nil }
处理网络流
函数
func OpenLive(device string, snaplen int32, promisc bool, timeout time.Duration) (handle *Handle, _ error) {} func OpenOffline(file string) (handle *Handle, err error) {} func OpenOfflineFile(file *os.File) (handle *Handle, err error) {}
获取网卡信息的各种方法测试
package main import ( "fmt" "github.com/google/gopacket/pcap" "log" "net" "os" "syscall" "unsafe" ) 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 } func localAddresses() error { fmt.Println("测试net.Interfaces()\n") ifaces, err := net.Interfaces() if err != nil { return err } for _, iface := range ifaces { fmt.Printf("%+v\n", iface) } fmt.Println() fmt.Println("测试net.InterfaceAddrs()") addrs, err := net.InterfaceAddrs() if err != nil { return err } for _, addr := range addrs { fmt.Printf("\n%+v\n", addr.String()) fmt.Printf("%+v\n", addr.Network()) } fmt.Println() //net.InterfaceByIndex() //net.InterfaceByName() //for _, addr := range addrs { // fmt.Printf("%T", addr) // // 这个网络地址是IP地址: ipv4, ipv6 // ipNet1, isIpNet1 := addr.(*net.IPNet) // fmt.Println(ipNet1) // fmt.Println(isIpNet1) // if ipNet, isIpNet := addr.(*net.IPNet); isIpNet && !ipNet.IP.IsLoopback() { // // 跳过IPV6 // if ipNet.IP.To4() != nil { // ipv4 := ipNet.IP.String() // 192.168.1.1 // fmt.Println(ipv4) // } // } //} fmt.Println("测试基于syscall的getAdapterList()") aList, err := getAdapterList() if err != nil { return err } for ai := aList; ai != nil; ai = ai.Next { fmt.Printf("\nIndex:\t%v\n", ai.Index) fmt.Printf("AdapterName:\t%s\n", &ai.AdapterName) fmt.Printf("Description:\t%s\n", &ai.Description) fmt.Printf("Address:\t%s\n", &ai.Address) ipl := &ai.IpAddressList gwl := &ai.GatewayList dhcpl := &ai.DhcpServer for ; ipl != nil; ipl = ipl.Next编程客栈 { fmt.Printf("IpAddress:\t%s\n", ipl.IpAddress) fmt.Printf("IpMask:\t%s\n", ipl.IpMask) fmt.Printf("GatewayIp:\t%s\n", gwl.IpAddress) fmt.Printf("DHCPServerIp:\t%s\n", dhcpl.IpAddress) } } fmt.Println() return err } func main() { if e := localAddresses(); e != nil { fmt.Println(e) } fmt.Println("测试pcap.FindAllDevs()") // Find all devices devices, err := pcap.FindAllDevs() if err != nil { log.Fatal(err) } // Print device information for _, device := range devices { fmt.Println("\nName: ", device.Name) fmt.Println("Description: ", device.Description) fmt.Println("Devices Flags: ", device.Flags) fmt.Println("Devices addresses: ") for _, address := range device.Addresses { fmt.Println("- IP address: ", address.IP) fmt.Println("- Subnet mask: ", address.Netmask) fmt.Println("- Broadaddr: ", address.Broadaddr) } } }
问题
如何关联各种信息?
比如关联pcap.Interface
和net.Interface
,参考:How to associate pcap.Interface with net.Interface?,有个人提出了一个解决方案,by matching the IP addresses of the interfaces with those of the devices。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。
精彩评论