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_BROADCAST != 0 {
    63  		f |= FlagBroadcast
    64  	}
    65  	if rawFlags&syscall.IFF_LOOPBACK != 0 {
    66  		f |= FlagLoopback
    67  	}
    68  	if rawFlags&syscall.IFF_POINTOPOINT != 0 {
    69  		f |= FlagPointToPoint
    70  	}
    71  	if rawFlags&syscall.IFF_MULTICAST != 0 {
    72  		f |= FlagMulticast
    73  	}
    74  	return f
    75  }
    76  
    77  // If the ifi is nil, interfaceAddrTable returns addresses for all
    78  // network interfaces. Otherwise it returns addresses for a specific
    79  // interface.
    80  func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
    81  	index := 0
    82  	if ifi != nil {
    83  		index = ifi.Index
    84  	}
    85  	msgs, err := interfaceMessages(index)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  	ifat := make([]Addr, 0, len(msgs))
    90  	for _, m := range msgs {
    91  		switch m := m.(type) {
    92  		case *route.InterfaceAddrMessage:
    93  			if index != 0 && index != m.Index {
    94  				continue
    95  			}
    96  			var mask IPMask
    97  			switch sa := m.Addrs[syscall.RTAX_NETMASK].(type) {
    98  			case *route.Inet4Addr:
    99  				mask = IPv4Mask(sa.IP[0], sa.IP[1], sa.IP[2], sa.IP[3])
   100  			case *route.Inet6Addr:
   101  				mask = make(IPMask, IPv6len)
   102  				copy(mask, sa.IP[:])
   103  			}
   104  			var ip IP
   105  			switch sa := m.Addrs[syscall.RTAX_IFA].(type) {
   106  			case *route.Inet4Addr:
   107  				ip = IPv4(sa.IP[0], sa.IP[1], sa.IP[2], sa.IP[3])
   108  			case *route.Inet6Addr:
   109  				ip = make(IP, IPv6len)
   110  				copy(ip, sa.IP[:])
   111  			}
   112  			if ip != nil && mask != nil { // NetBSD may contain route.LinkAddr
   113  				ifat = append(ifat, &IPNet{IP: ip, Mask: mask})
   114  			}
   115  		}
   116  	}
   117  	return ifat, nil
   118  }
   119  

View as plain text