github.com/icodeface/tls@v0.0.0-20230910023335-34df9250cd12/internal/x/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 // +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 }