OSDN Git Service

net, syscall: Use native endianness for GNU/Linux netlink code.
[pf3gnuchains/gcc-fork.git] / libgo / go / net / interface_freebsd.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 // Network interface identification for FreeBSD
6
7 package net
8
9 import (
10         "os"
11         "syscall"
12 )
13
14 // If the ifindex is zero, interfaceMulticastAddrTable returns
15 // addresses for all network interfaces.  Otherwise it returns
16 // addresses for a specific interface.
17 func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
18         tab, err := syscall.RouteRIB(syscall.NET_RT_IFMALIST, ifindex)
19         if err != nil {
20                 return nil, os.NewSyscallError("route rib", err)
21         }
22
23         msgs, err := syscall.ParseRoutingMessage(tab)
24         if err != nil {
25                 return nil, os.NewSyscallError("route message", err)
26         }
27
28         var ifmat []Addr
29         for _, m := range msgs {
30                 switch v := m.(type) {
31                 case *syscall.InterfaceMulticastAddrMessage:
32                         if ifindex == 0 || ifindex == int(v.Header.Index) {
33                                 ifma, err := newMulticastAddr(v)
34                                 if err != nil {
35                                         return nil, err
36                                 }
37                                 ifmat = append(ifmat, ifma...)
38                         }
39                 }
40         }
41         return ifmat, nil
42 }
43
44 func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) {
45         sas, err := syscall.ParseRoutingSockaddr(m)
46         if err != nil {
47                 return nil, os.NewSyscallError("route sockaddr", err)
48         }
49
50         var ifmat []Addr
51         for _, s := range sas {
52                 switch v := s.(type) {
53                 case *syscall.SockaddrInet4:
54                         ifma := &IPAddr{IP: IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])}
55                         ifmat = append(ifmat, ifma.toAddr())
56                 case *syscall.SockaddrInet6:
57                         ifma := &IPAddr{IP: make(IP, IPv6len)}
58                         copy(ifma.IP, v.Addr[:])
59                         // NOTE: KAME based IPv6 protcol stack usually embeds
60                         // the interface index in the interface-local or link-
61                         // local address as the kernel-internal form.
62                         if ifma.IP.IsInterfaceLocalMulticast() ||
63                                 ifma.IP.IsLinkLocalMulticast() {
64                                 // remove embedded scope zone ID
65                                 ifma.IP[2], ifma.IP[3] = 0, 0
66                         }
67                         ifmat = append(ifmat, ifma.toAddr())
68                 }
69         }
70         return ifmat, nil
71 }