golang link 代码
文件路径:/src/vendor/golang.org/x/net/lif/link.go
/ Copyright 2016 The Go Authors. All rights reserved.
/ Use of this source code is governed by a BSD-style
/ license that can be found in the LICENSE file.
/go:build solaris
/ +build solaris
package lif
import "unsafe"
/ A Link represents logical data link information.
/
/ It also represents base information for logical network interface.
/ On Solaris, each logical network interface represents network layer
/ adjacency information and the interface has a only single network
/ address or address pair for tunneling. It's usual that multiple
/ logical network interfaces share the same logical data link.
type Link struct {
Name string / name, equivalent to IP interface name
Index int / index, equivalent to IP interface index
Type int / type
Flags int / flags
MTU int / maximum transmission unit, basically link MTU but may differ between IP address families
Addr []byte / address
}
func (ll *Link) fetch(s uintptr) {
var lifr lifreq
for i := 0; i < len(ll.Name); i++ {
lifr.Name[i] = int8(ll.Name[i])
}
ioc := int64(sysSIOCGLIFINDEX)
if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
ll.Index = int(nativeEndian.Uint32(lifr.Lifru[:4]))
}
ioc = int64(sysSIOCGLIFFLAGS)
if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
ll.Flags = int(nativeEndian.Uint64(lifr.Lifru[:8]))
}
ioc = int64(sysSIOCGLIFMTU)
if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
ll.MTU = int(nativeEndian.Uint32(lifr.Lifru[:4]))
}
switch ll.Type {
case sysIFT_IPV4, sysIFT_IPV6, sysIFT_6TO4:
default:
ioc = int64(sysSIOCGLIFHWADDR)
if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
ll.Addr, _ = parseLinkAddr(lifr.Lifru[4:])
}
}
}
/ Links returns a list of logical data links.
/
/ The provided af must be an address family and name must be a data
/ link name. The zero value of af or name means a wildcard.
func Links(af int, name string) ([]Link, error) {
eps, err := newEndpoints(af)
if len(eps) == 0 {
return nil, err
}
defer func() {
for _, ep := range eps {
ep.close()
}
}()
return links(eps, name)
}
func links(eps []endpoint, name string) ([]Link, error) {
var lls []Link
lifn := lifnum{Flags: sysLIFC_NOXMIT | sysLIFC_TEMPORARY | sysLIFC_ALLZONES | sysLIFC_UNDER_IPMP}
lifc := lifconf{Flags: sysLIFC_NOXMIT | sysLIFC_TEMPORARY | sysLIFC_ALLZONES | sysLIFC_UNDER_IPMP}
for _, ep := range eps {
lifn.Family = uint16(ep.af)
ioc := int64(sysSIOCGLIFNUM)
if err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifn)); err != nil {
continue
}
if lifn.Count == 0 {
continue
}
b := make([]byte, lifn.Count*sizeofLifreq)
lifc.Family = uint16(ep.af)
lifc.Len = lifn.Count * sizeofLifreq
if len(lifc.Lifcu) == 8 {
nativeEndian.PutUint64(lifc.Lifcu[:], uint64(uintptr(unsafe.Pointer(&b[0]))))
} else {
nativeEndian.PutUint32(lifc.Lifcu[:], uint32(uintptr(unsafe.Pointer(&b[0]))))
}
ioc = int64(sysSIOCGLIFCONF)
if err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifc)); err != nil {
continue
}
nb := make([]byte, 32) / see LIFNAMSIZ in net/if.h
for i := 0; i < int(lifn.Count); i++ {
lifr := (*lifreq)(unsafe.Pointer(&b[i*sizeofLifreq]))
for i := 0; i < 32; i++ {
if lifr.Name[i] == 0 {
nb = nb[:i]
break
}
nb[i] = byte(lifr.Name[i])
}
llname := string(nb)
nb = nb[:32]
if isDupLink(lls, llname) || name != "" && name != llname {
continue
}
ll := Link{Name: llname, Type: int(lifr.Type)}
ll.fetch(ep.s)
lls = append(lls, ll)
}
}
return lls, nil
}
func isDupLink(lls []Link, name string) bool {
for _, ll := range lls {
if ll.Name == name {
return true
}
}
return false
}