Source file src/net/interface_bsd.go

     1  // Copyright 2011 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 darwin || dragonfly || freebsd || netbsd || openbsd
     6  
     7  package net
     8  
     9  import (
    10  	"syscall"
    11  
    12  	"golang.org/x/net/route"
    13  )
    14  
    15  // If the ifindex is zero, interfaceTable returns mappings of all
    16  // network interfaces. Otherwise it returns a mapping of a specific
    17  // interface.
    18  func interfaceTable(ifindex int) ([]Interface, error) {
    19  	msgs, err := interfaceMessages(ifindex)
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  	n := len(msgs)
    24  	if ifindex != 0 {
    25  		n = 1
    26  	}
    27  	ift := make([]Interface, n)
    28  	n = 0
    29  	for _, m := range msgs {
    30  		switch m := m.(type) {
    31  		case *route.InterfaceMessage:
    32  			if ifindex != 0 && ifindex != m.Index {
    33  				continue
    34  			}
    35  			ift[n].Index = m.Index
    36  			ift[n].Name = m.Name
    37  			ift[n].Flags = linkFlags(m.Flags)
    38  			if sa, ok := m.Addrs[syscall.RTAX_IFP].(*route.LinkAddr); ok && len(sa.Addr) > 0 {
    39  				ift[n].HardwareAddr = make([]byte, len(sa.Addr))
    40  				copy(ift[n].HardwareAddr, sa.Addr)
    41  			}
    42  			for _, sys := range m.Sys() {
    43  				if imx, ok := sys.(*route.InterfaceMetrics); ok {
    44  					ift[n].MTU = imx.MTU
    45  					break
    46  				}
    47  			}
    48  			n++
    49  			if ifindex == m.Index {
    50  				return ift[:n], nil
    51  			}
    52  		}
    53  	}
    54  	return ift[:n], nil
    55  }
    56  
    57  func linkFlags(rawFlags int) Flags {
    58  	var f Flags
    59  	if rawFlags&syscall.IFF_UP != 0 {
    60  		f |= FlagUp
    61  	}
    62  	if rawFlags&syscall.IFF_RUNNING != 0 {
    63  		f |= FlagRunning
    64  	}
    65  	if rawFlags&syscall.IFF_BROADCAST != 0 {
    66  		f |= FlagBroadcast
    67  	}
    68  	if rawFlags&syscall.IFF_LOOPBACK != 0 {
    69  		f |= FlagLoopback
    70  	}
    71  	if rawFlags&syscall.IFF_POINTOPOINT != 0 {
    72  		f |= FlagPointToPoint
    73  	}
    74  	if rawFlags&syscall.IFF_MULTICAST != 0 {
    75  		f |= FlagMulticast
    76  	}
    77  	return f
    78  }
    79  
    80  // If the ifi is nil, interfaceAddrTable returns addresses for all
    81  // network interfaces. Otherwise it returns addresses for a specific
    82  // interface.
    83  func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
    84  	index := 0
    85  	if ifi != nil {
    86  		index = ifi.Index
    87  	}
    88  	msgs, err := interfaceMessages(index)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  	ifat := make([]Addr, 0, len(msgs))
    93  	for _, m := range msgs {
    94  		switch m := m.(type) {
    95  		case *route.InterfaceAddrMessage:
    96  			if index != 0 && index != m.Index {
    97  				continue
    98  			}
    99  			var mask IPMask
   100  			switch sa := m.Addrs[syscall.RTAX_NETMASK].(type) {
   101  			case *route.Inet4Addr:
   102  				mask = IPv4Mask(sa.IP[0], sa.IP[1], sa.IP[2], sa.IP[3])
   103  			case *route.Inet6Addr:
   104  				mask = make(IPMask, IPv6len)
   105  				copy(mask, sa.IP[:])
   106  			}
   107  			var ip IP
   108  			switch sa := m.Addrs[syscall.RTAX_IFA].(type) {
   109  			case *route.Inet4Addr:
   110  				ip = IPv4(sa.IP[0], sa.IP[1], sa.IP[2], sa.IP[3])
   111  			case *route.Inet6Addr:
   112  				ip = make(IP, IPv6len)
   113  				copy(ip, sa.IP[:])
   114  			}
   115  			if ip != nil && mask != nil { // NetBSD may contain route.LinkAddr
   116  				ifat = append(ifat, &IPNet{IP: ip, Mask: mask})
   117  			}
   118  		}
   119  	}
   120  	return ifat, nil
   121  }
   122  

View as plain text