...
  
  
     1  
     2  
     3  
     4  
     5  
     6  
     7  package lif
     8  
     9  import (
    10  	"syscall"
    11  	"unsafe"
    12  )
    13  
    14  
    15  
    16  
    17  
    18  
    19  
    20  
    21  type Link struct {
    22  	Name  string 
    23  	Index int    
    24  	Type  int    
    25  	Flags int    
    26  	MTU   int    
    27  	Addr  []byte 
    28  }
    29  
    30  func (ll *Link) fetch(s uintptr) {
    31  	var lifr lifreq
    32  	for i := 0; i < len(ll.Name); i++ {
    33  		lifr.Name[i] = int8(ll.Name[i])
    34  	}
    35  	ioc := int64(syscall.SIOCGLIFINDEX)
    36  	if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
    37  		ll.Index = int(nativeEndian.Uint32(lifr.Lifru[:4]))
    38  	}
    39  	ioc = int64(syscall.SIOCGLIFFLAGS)
    40  	if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
    41  		ll.Flags = int(nativeEndian.Uint64(lifr.Lifru[:8]))
    42  	}
    43  	ioc = int64(syscall.SIOCGLIFMTU)
    44  	if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
    45  		ll.MTU = int(nativeEndian.Uint32(lifr.Lifru[:4]))
    46  	}
    47  	switch ll.Type {
    48  	case syscall.IFT_IPV4, syscall.IFT_IPV6, syscall.IFT_6TO4:
    49  	default:
    50  		ioc = int64(syscall.SIOCGLIFHWADDR)
    51  		if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
    52  			ll.Addr, _ = parseLinkAddr(lifr.Lifru[4:])
    53  		}
    54  	}
    55  }
    56  
    57  
    58  
    59  
    60  
    61  func Links(af int, name string) ([]Link, error) {
    62  	eps, err := newEndpoints(af)
    63  	if len(eps) == 0 {
    64  		return nil, err
    65  	}
    66  	defer func() {
    67  		for _, ep := range eps {
    68  			ep.close()
    69  		}
    70  	}()
    71  	return links(eps, name)
    72  }
    73  
    74  func links(eps []endpoint, name string) ([]Link, error) {
    75  	var lls []Link
    76  	lifn := lifnum{Flags: sysLIFC_NOXMIT | sysLIFC_TEMPORARY | sysLIFC_ALLZONES | sysLIFC_UNDER_IPMP}
    77  	lifc := lifconf{Flags: sysLIFC_NOXMIT | sysLIFC_TEMPORARY | sysLIFC_ALLZONES | sysLIFC_UNDER_IPMP}
    78  	for _, ep := range eps {
    79  		lifn.Family = uint16(ep.af)
    80  		ioc := int64(syscall.SIOCGLIFNUM)
    81  		if err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifn)); err != nil {
    82  			continue
    83  		}
    84  		if lifn.Count == 0 {
    85  			continue
    86  		}
    87  		b := make([]byte, lifn.Count*sizeofLifreq)
    88  		lifc.Family = uint16(ep.af)
    89  		lifc.Len = lifn.Count * sizeofLifreq
    90  		if len(lifc.Lifcu) == 8 {
    91  			nativeEndian.PutUint64(lifc.Lifcu[:], uint64(uintptr(unsafe.Pointer(&b[0]))))
    92  		} else {
    93  			nativeEndian.PutUint32(lifc.Lifcu[:], uint32(uintptr(unsafe.Pointer(&b[0]))))
    94  		}
    95  		ioc = int64(syscall.SIOCGLIFCONF)
    96  		if err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifc)); err != nil {
    97  			continue
    98  		}
    99  		nb := make([]byte, 32) 
   100  		for i := 0; i < int(lifn.Count); i++ {
   101  			lifr := (*lifreq)(unsafe.Pointer(&b[i*sizeofLifreq]))
   102  			for i := 0; i < 32; i++ {
   103  				if lifr.Name[i] == 0 {
   104  					nb = nb[:i]
   105  					break
   106  				}
   107  				nb[i] = byte(lifr.Name[i])
   108  			}
   109  			llname := string(nb)
   110  			nb = nb[:32]
   111  			if isDupLink(lls, llname) || name != "" && name != llname {
   112  				continue
   113  			}
   114  			ll := Link{Name: llname, Type: int(lifr.Type)}
   115  			ll.fetch(ep.s)
   116  			lls = append(lls, ll)
   117  		}
   118  	}
   119  	return lls, nil
   120  }
   121  
   122  func isDupLink(lls []Link, name string) bool {
   123  	for _, ll := range lls {
   124  		if ll.Name == name {
   125  			return true
   126  		}
   127  	}
   128  	return false
   129  }
   130  
View as plain text