2013-02-11 Sebastian Huber <sebastian.huber@embedded-brains.de>
[official-gcc.git] / libgo / go / net / interface_bsd.go
blobdf9b3a2f279a4759e07f61c51a741c6019462b67
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.
5 // +build darwin freebsd netbsd openbsd
7 // Network interface identification for BSD variants
9 package net
11 import (
12 "os"
13 "syscall"
14 "unsafe"
17 // If the ifindex is zero, interfaceTable returns mappings of all
18 // network interfaces. Otherwise it returns a mapping of a specific
19 // interface.
20 func interfaceTable(ifindex int) ([]Interface, error) {
21 tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
22 if err != nil {
23 return nil, os.NewSyscallError("route rib", err)
26 msgs, err := syscall.ParseRoutingMessage(tab)
27 if err != nil {
28 return nil, os.NewSyscallError("route message", err)
31 var ift []Interface
32 for _, m := range msgs {
33 switch v := m.(type) {
34 case *syscall.InterfaceMessage:
35 if ifindex == 0 || ifindex == int(v.Header.Index) {
36 ifi, err := newLink(v)
37 if err != nil {
38 return nil, err
40 ift = append(ift, ifi...)
44 return ift, nil
47 func newLink(m *syscall.InterfaceMessage) ([]Interface, error) {
48 sas, err := syscall.ParseRoutingSockaddr(m)
49 if err != nil {
50 return nil, os.NewSyscallError("route sockaddr", err)
53 var ift []Interface
54 for _, s := range sas {
55 switch v := s.(type) {
56 case *syscall.SockaddrDatalink:
57 // NOTE: SockaddrDatalink.Data is minimum work area,
58 // can be larger.
59 m.Data = m.Data[unsafe.Offsetof(v.Data):]
60 ifi := Interface{Index: int(m.Header.Index), Flags: linkFlags(m.Header.Flags)}
61 var name [syscall.IFNAMSIZ]byte
62 for i := 0; i < int(v.Nlen); i++ {
63 name[i] = byte(m.Data[i])
65 ifi.Name = string(name[:v.Nlen])
66 ifi.MTU = int(m.Header.Data.Mtu)
67 addr := make([]byte, v.Alen)
68 for i := 0; i < int(v.Alen); i++ {
69 addr[i] = byte(m.Data[int(v.Nlen)+i])
71 ifi.HardwareAddr = addr[:v.Alen]
72 ift = append(ift, ifi)
75 return ift, nil
78 func linkFlags(rawFlags int32) Flags {
79 var f Flags
80 if rawFlags&syscall.IFF_UP != 0 {
81 f |= FlagUp
83 if rawFlags&syscall.IFF_BROADCAST != 0 {
84 f |= FlagBroadcast
86 if rawFlags&syscall.IFF_LOOPBACK != 0 {
87 f |= FlagLoopback
89 if rawFlags&syscall.IFF_POINTOPOINT != 0 {
90 f |= FlagPointToPoint
92 if rawFlags&syscall.IFF_MULTICAST != 0 {
93 f |= FlagMulticast
95 return f
98 // If the ifindex is zero, interfaceAddrTable returns addresses
99 // for all network interfaces. Otherwise it returns addresses
100 // for a specific interface.
101 func interfaceAddrTable(ifindex int) ([]Addr, error) {
102 tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
103 if err != nil {
104 return nil, os.NewSyscallError("route rib", err)
107 msgs, err := syscall.ParseRoutingMessage(tab)
108 if err != nil {
109 return nil, os.NewSyscallError("route message", err)
112 var ifat []Addr
113 for _, m := range msgs {
114 switch v := m.(type) {
115 case *syscall.InterfaceAddrMessage:
116 if ifindex == 0 || ifindex == int(v.Header.Index) {
117 ifa, err := newAddr(v)
118 if err != nil {
119 return nil, err
121 if ifa != nil {
122 ifat = append(ifat, ifa)
127 return ifat, nil
130 func newAddr(m *syscall.InterfaceAddrMessage) (Addr, error) {
131 sas, err := syscall.ParseRoutingSockaddr(m)
132 if err != nil {
133 return nil, os.NewSyscallError("route sockaddr", err)
136 ifa := &IPNet{}
137 for i, s := range sas {
138 switch v := s.(type) {
139 case *syscall.SockaddrInet4:
140 switch i {
141 case 0:
142 ifa.Mask = IPv4Mask(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])
143 case 1:
144 ifa.IP = IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])
146 case *syscall.SockaddrInet6:
147 switch i {
148 case 0:
149 ifa.Mask = make(IPMask, IPv6len)
150 copy(ifa.Mask, v.Addr[:])
151 case 1:
152 ifa.IP = make(IP, IPv6len)
153 copy(ifa.IP, v.Addr[:])
154 // NOTE: KAME based IPv6 protcol stack usually embeds
155 // the interface index in the interface-local or link-
156 // local address as the kernel-internal form.
157 if ifa.IP.IsLinkLocalUnicast() {
158 // remove embedded scope zone ID
159 ifa.IP[2], ifa.IP[3] = 0, 0
162 default: // Sockaddrs contain syscall.SockaddrDatalink on NetBSD
163 return nil, nil
166 return ifa, nil