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

View as plain text