interface_bsd.mx raw

   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 := []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 = []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 := []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