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