gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/net/lif/link.go (about)

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