github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/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 }