...

Source file src/vendor/golang.org/x/net/lif/link.go

     1	// Copyright 2016 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// +build solaris
     6	
     7	package lif
     8	
     9	import "unsafe"
    10	
    11	// A Link represents logical data link information.
    12	//
    13	// It also represents base information for logical network interface.
    14	// On Solaris, each logical network interface represents network layer
    15	// adjacency information and the interface has a only single network
    16	// address or address pair for tunneling. It's usual that multiple
    17	// logical network interfaces share the same logical data link.
    18	type Link struct {
    19		Name  string // name, equivalent to IP interface name
    20		Index int    // index, equivalent to IP interface index
    21		Type  int    // type
    22		Flags int    // flags
    23		MTU   int    // maximum transmission unit, basically link MTU but may differ between IP address families
    24		Addr  []byte // address
    25	}
    26	
    27	func (ll *Link) fetch(s uintptr) {
    28		var lifr lifreq
    29		for i := 0; i < len(ll.Name); i++ {
    30			lifr.Name[i] = int8(ll.Name[i])
    31		}
    32		ioc := int64(sysSIOCGLIFINDEX)
    33		if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
    34			ll.Index = int(nativeEndian.Uint32(lifr.Lifru[:4]))
    35		}
    36		ioc = int64(sysSIOCGLIFFLAGS)
    37		if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
    38			ll.Flags = int(nativeEndian.Uint64(lifr.Lifru[:8]))
    39		}
    40		ioc = int64(sysSIOCGLIFMTU)
    41		if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
    42			ll.MTU = int(nativeEndian.Uint32(lifr.Lifru[:4]))
    43		}
    44		switch ll.Type {
    45		case sysIFT_IPV4, sysIFT_IPV6, sysIFT_6TO4:
    46		default:
    47			ioc = int64(sysSIOCGLIFHWADDR)
    48			if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
    49				ll.Addr, _ = parseLinkAddr(lifr.Lifru[4:])
    50			}
    51		}
    52	}
    53	
    54	// Links returns a list of logical data links.
    55	//
    56	// The provided af must be an address family and name must be a data
    57	// link name. The zero value of af or name means a wildcard.
    58	func Links(af int, name string) ([]Link, error) {
    59		eps, err := newEndpoints(af)
    60		if len(eps) == 0 {
    61			return nil, err
    62		}
    63		defer func() {
    64			for _, ep := range eps {
    65				ep.close()
    66			}
    67		}()
    68		return links(eps, name)
    69	}
    70	
    71	func links(eps []endpoint, name string) ([]Link, error) {
    72		var lls []Link
    73		lifn := lifnum{Flags: sysLIFC_NOXMIT | sysLIFC_TEMPORARY | sysLIFC_ALLZONES | sysLIFC_UNDER_IPMP}
    74		lifc := lifconf{Flags: sysLIFC_NOXMIT | sysLIFC_TEMPORARY | sysLIFC_ALLZONES | sysLIFC_UNDER_IPMP}
    75		for _, ep := range eps {
    76			lifn.Family = uint16(ep.af)
    77			ioc := int64(sysSIOCGLIFNUM)
    78			if err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifn)); err != nil {
    79				continue
    80			}
    81			if lifn.Count == 0 {
    82				continue
    83			}
    84			b := make([]byte, lifn.Count*sizeofLifreq)
    85			lifc.Family = uint16(ep.af)
    86			lifc.Len = lifn.Count * sizeofLifreq
    87			if len(lifc.Lifcu) == 8 {
    88				nativeEndian.PutUint64(lifc.Lifcu[:], uint64(uintptr(unsafe.Pointer(&b[0]))))
    89			} else {
    90				nativeEndian.PutUint32(lifc.Lifcu[:], uint32(uintptr(unsafe.Pointer(&b[0]))))
    91			}
    92			ioc = int64(sysSIOCGLIFCONF)
    93			if err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifc)); err != nil {
    94				continue
    95			}
    96			nb := make([]byte, 32) // see LIFNAMSIZ in net/if.h
    97			for i := 0; i < int(lifn.Count); i++ {
    98				lifr := (*lifreq)(unsafe.Pointer(&b[i*sizeofLifreq]))
    99				for i := 0; i < 32; i++ {
   100					if lifr.Name[i] == 0 {
   101						nb = nb[:i]
   102						break
   103					}
   104					nb[i] = byte(lifr.Name[i])
   105				}
   106				llname := string(nb)
   107				nb = nb[:32]
   108				if isDupLink(lls, llname) || name != "" && name != llname {
   109					continue
   110				}
   111				ll := Link{Name: llname, Type: int(lifr.Type)}
   112				ll.fetch(ep.s)
   113				lls = append(lls, ll)
   114			}
   115		}
   116		return lls, nil
   117	}
   118	
   119	func isDupLink(lls []Link, name string) bool {
   120		for _, ll := range lls {
   121			if ll.Name == name {
   122				return true
   123			}
   124		}
   125		return false
   126	}
   127	

View as plain text