fd.go\
file.go\
interface_bsd.go\
+ interface_freebsd.go\
lookup_unix.go\
newpollserver.go\
port.go\
fd.go\
file.go\
interface_bsd.go\
+ interface_darwin.go\
lookup_unix.go\
newpollserver.go\
port.go\
return interfaceAddrTable(ifi.Index)
}
+// MulticastAddrs returns multicast, joined group addresses for
+// a specific interface.
+func (ifi *Interface) MulticastAddrs() ([]Addr, os.Error) {
+ if ifi == nil {
+ return nil, os.NewError("net: invalid interface")
+ }
+ return interfaceMulticastAddrTable(ifi.Index)
+}
+
// Interfaces returns a list of the systems's network interfaces.
func Interfaces() ([]Interface, os.Error) {
return interfaceTable(0)
}
for _, s := range sas {
- var ifa IPAddr
+
switch v := s.(type) {
case *syscall.SockaddrInet4:
- ifa.IP = IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])
+ ifa := &IPAddr{IP: IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])}
+ ifat = append(ifat, ifa.toAddr())
case *syscall.SockaddrInet6:
- ifa.IP = make(IP, IPv6len)
+ ifa := &IPAddr{IP: make(IP, IPv6len)}
copy(ifa.IP, v.Addr[:])
// NOTE: KAME based IPv6 protcol stack usually embeds
// the interface index in the interface-local or link-
// local address as the kernel-internal form.
- if ifa.IP.IsLinkLocalUnicast() ||
- ifa.IP.IsInterfaceLocalMulticast() ||
- ifa.IP.IsLinkLocalMulticast() {
+ if ifa.IP.IsLinkLocalUnicast() {
// remove embedded scope zone ID
ifa.IP[2], ifa.IP[3] = 0, 0
}
+ ifat = append(ifat, ifa.toAddr())
}
- ifat = append(ifat, ifa.toAddr())
}
return ifat, nil
}
+
+func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, os.Error) {
+ var ifmat []Addr
+
+ sas, e := syscall.ParseRoutingSockaddr(m)
+ if e != 0 {
+ return nil, os.NewSyscallError("route sockaddr", e)
+ }
+
+ for _, s := range sas {
+ switch v := s.(type) {
+ case *syscall.SockaddrInet4:
+ ifma := &IPAddr{IP: IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])}
+ ifmat = append(ifmat, ifma.toAddr())
+ case *syscall.SockaddrInet6:
+ ifma := &IPAddr{IP: make(IP, IPv6len)}
+ copy(ifma.IP, v.Addr[:])
+ // NOTE: KAME based IPv6 protcol stack usually embeds
+ // the interface index in the interface-local or link-
+ // local address as the kernel-internal form.
+ if ifma.IP.IsInterfaceLocalMulticast() ||
+ ifma.IP.IsLinkLocalMulticast() {
+ // remove embedded scope zone ID
+ ifma.IP[2], ifma.IP[3] = 0, 0
+ }
+ ifmat = append(ifmat, ifma.toAddr())
+ }
+ }
+
+ return ifmat, nil
+}
--- /dev/null
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Network interface identification for Darwin
+
+package net
+
+import (
+ "os"
+ "syscall"
+)
+
+// If the ifindex is zero, interfaceMulticastAddrTable returns
+// addresses for all network interfaces. Otherwise it returns
+// addresses for a specific interface.
+func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) {
+ var (
+ tab []byte
+ e int
+ msgs []syscall.RoutingMessage
+ ifmat []Addr
+ )
+
+ tab, e = syscall.RouteRIB(syscall.NET_RT_IFLIST2, ifindex)
+ if e != 0 {
+ return nil, os.NewSyscallError("route rib", e)
+ }
+
+ msgs, e = syscall.ParseRoutingMessage(tab)
+ if e != 0 {
+ return nil, os.NewSyscallError("route message", e)
+ }
+
+ for _, m := range msgs {
+ switch v := m.(type) {
+ case *syscall.InterfaceMulticastAddrMessage:
+ if ifindex == 0 || ifindex == int(v.Header.Index) {
+ ifma, err := newMulticastAddr(v)
+ if err != nil {
+ return nil, err
+ }
+ ifmat = append(ifmat, ifma...)
+ }
+ }
+ }
+
+ return ifmat, nil
+}
--- /dev/null
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Network interface identification for FreeBSD
+
+package net
+
+import (
+ "os"
+ "syscall"
+)
+
+// If the ifindex is zero, interfaceMulticastAddrTable returns
+// addresses for all network interfaces. Otherwise it returns
+// addresses for a specific interface.
+func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) {
+ var (
+ tab []byte
+ e int
+ msgs []syscall.RoutingMessage
+ ifmat []Addr
+ )
+
+ tab, e = syscall.RouteRIB(syscall.NET_RT_IFMALIST, ifindex)
+ if e != 0 {
+ return nil, os.NewSyscallError("route rib", e)
+ }
+
+ msgs, e = syscall.ParseRoutingMessage(tab)
+ if e != 0 {
+ return nil, os.NewSyscallError("route message", e)
+ }
+
+ for _, m := range msgs {
+ switch v := m.(type) {
+ case *syscall.InterfaceMulticastAddrMessage:
+ if ifindex == 0 || ifindex == int(v.Header.Index) {
+ ifma, err := newMulticastAddr(v)
+ if err != nil {
+ return nil, err
+ }
+ ifmat = append(ifmat, ifma...)
+ }
+ }
+ }
+
+ return ifmat, nil
+}
package net
import (
+ "fmt"
"os"
"syscall"
"unsafe"
// for a specific interface.
func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
var (
+ tab []byte
+ e int
+ err os.Error
ifat4 []Addr
ifat6 []Addr
- tab []byte
msgs4 []syscall.NetlinkMessage
msgs6 []syscall.NetlinkMessage
- e int
- err os.Error
)
tab, e = syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_INET)
for _, a := range attrs {
switch a.Attr.Type {
case syscall.IFA_ADDRESS:
- ifa := IPAddr{}
switch family {
case syscall.AF_INET:
- ifa.IP = IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3])
+ ifa := &IPAddr{IP: IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3])}
+ ifat = append(ifat, ifa.toAddr())
case syscall.AF_INET6:
- ifa.IP = make(IP, IPv6len)
+ ifa := &IPAddr{IP: make(IP, IPv6len)}
copy(ifa.IP, a.Value[:])
+ ifat = append(ifat, ifa.toAddr())
}
- ifat = append(ifat, ifa.toAddr())
}
}
return ifat
}
+
+// If the ifindex is zero, interfaceMulticastAddrTable returns
+// addresses for all network interfaces. Otherwise it returns
+// addresses for a specific interface.
+func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) {
+ var (
+ ifi *Interface
+ err os.Error
+ ifmat4 []Addr
+ ifmat6 []Addr
+ )
+
+ if ifindex > 0 {
+ ifi, err = InterfaceByIndex(ifindex)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ ifmat4, err = parseProcNetIGMP(ifi)
+ if err != nil {
+ return nil, err
+ }
+
+ ifmat6, err = parseProcNetIGMP6(ifi)
+ if err != nil {
+ return nil, err
+ }
+
+ return append(ifmat4, ifmat6...), nil
+}
+
+func parseProcNetIGMP(ifi *Interface) ([]Addr, os.Error) {
+ var (
+ ifmat []Addr
+ name string
+ )
+
+ fd, err := open("/proc/net/igmp")
+ if err != nil {
+ return nil, err
+ }
+ defer fd.close()
+
+ fd.readLine() // skip first line
+ b := make([]byte, IPv4len)
+ for l, ok := fd.readLine(); ok; l, ok = fd.readLine() {
+ f := getFields(l)
+ switch len(f) {
+ case 4:
+ if ifi == nil || name == ifi.Name {
+ fmt.Sscanf(f[0], "%08x", &b)
+ ifma := IPAddr{IP: IPv4(b[3], b[2], b[1], b[0])}
+ ifmat = append(ifmat, ifma.toAddr())
+ }
+ case 5:
+ name = f[1]
+ }
+ }
+
+ return ifmat, nil
+}
+
+func parseProcNetIGMP6(ifi *Interface) ([]Addr, os.Error) {
+ var ifmat []Addr
+
+ fd, err := open("/proc/net/igmp6")
+ if err != nil {
+ return nil, err
+ }
+ defer fd.close()
+
+ b := make([]byte, IPv6len)
+ for l, ok := fd.readLine(); ok; l, ok = fd.readLine() {
+ f := getFields(l)
+ if ifi == nil || f[1] == ifi.Name {
+ fmt.Sscanf(f[2], "%32x", &b)
+ ifma := IPAddr{IP: IP{b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]}}
+ ifmat = append(ifmat, ifma.toAddr())
+
+ }
+ }
+
+ return ifmat, nil
+}
func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
return nil, nil
}
+
+// If the ifindex is zero, interfaceMulticastAddrTable returns
+// addresses for all network interfaces. Otherwise it returns
+// addresses for a specific interface.
+func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) {
+ return nil, nil
+}
if err != nil {
t.Fatalf("Interface.Addrs() failed: %v", err)
}
+ ifmat, err := ifi.MulticastAddrs()
+ if err != nil {
+ t.Fatalf("Interface.MulticastAddrs() failed: %v", err)
+ }
t.Logf("%q: flags %q, ifindex %v, mtu %v\n", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU)
for _, ifa := range ifat {
t.Logf("\tinterface address %q\n", ifa.String())
}
+ for _, ifma := range ifmat {
+ t.Logf("\tjoined group address %q\n", ifma.String())
+ }
t.Logf("\thardware address %q", ifi.HardwareAddr.String())
}
}
}
return ifat, nil
}
+
+// If the ifindex is zero, interfaceMulticastAddrTable returns
+// addresses for all network interfaces. Otherwise it returns
+// addresses for a specific interface.
+func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) {
+ return nil, nil
+}