mirror of
https://github.com/golang/go
synced 2024-11-25 01:08:02 -07:00
net: joined group addresses for a specific interface for darwin, freebsd, linux
This CL enables to list the multicast, joined group addresses for a specific interface by using Interface.MulticastAddrs method. R=rsc CC=golang-dev https://golang.org/cl/4808062
This commit is contained in:
parent
dc7f82559d
commit
946cb0ece1
@ -29,6 +29,7 @@ GOFILES_freebsd=\
|
|||||||
fd.go\
|
fd.go\
|
||||||
file.go\
|
file.go\
|
||||||
interface_bsd.go\
|
interface_bsd.go\
|
||||||
|
interface_freebsd.go\
|
||||||
lookup_unix.go\
|
lookup_unix.go\
|
||||||
newpollserver.go\
|
newpollserver.go\
|
||||||
port.go\
|
port.go\
|
||||||
@ -45,6 +46,7 @@ GOFILES_darwin=\
|
|||||||
fd.go\
|
fd.go\
|
||||||
file.go\
|
file.go\
|
||||||
interface_bsd.go\
|
interface_bsd.go\
|
||||||
|
interface_darwin.go\
|
||||||
lookup_unix.go\
|
lookup_unix.go\
|
||||||
newpollserver.go\
|
newpollserver.go\
|
||||||
port.go\
|
port.go\
|
||||||
|
@ -79,6 +79,15 @@ func (ifi *Interface) Addrs() ([]Addr, os.Error) {
|
|||||||
return interfaceAddrTable(ifi.Index)
|
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.
|
// Interfaces returns a list of the systems's network interfaces.
|
||||||
func Interfaces() ([]Interface, os.Error) {
|
func Interfaces() ([]Interface, os.Error) {
|
||||||
return interfaceTable(0)
|
return interfaceTable(0)
|
||||||
|
@ -148,25 +148,55 @@ func newAddr(m *syscall.InterfaceAddrMessage) ([]Addr, os.Error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range sas {
|
for _, s := range sas {
|
||||||
var ifa IPAddr
|
|
||||||
switch v := s.(type) {
|
switch v := s.(type) {
|
||||||
case *syscall.SockaddrInet4:
|
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:
|
case *syscall.SockaddrInet6:
|
||||||
ifa.IP = make(IP, IPv6len)
|
ifa := &IPAddr{IP: make(IP, IPv6len)}
|
||||||
copy(ifa.IP, v.Addr[:])
|
copy(ifa.IP, v.Addr[:])
|
||||||
// NOTE: KAME based IPv6 protcol stack usually embeds
|
// NOTE: KAME based IPv6 protcol stack usually embeds
|
||||||
// the interface index in the interface-local or link-
|
// the interface index in the interface-local or link-
|
||||||
// local address as the kernel-internal form.
|
// local address as the kernel-internal form.
|
||||||
if ifa.IP.IsLinkLocalUnicast() ||
|
if ifa.IP.IsLinkLocalUnicast() {
|
||||||
ifa.IP.IsInterfaceLocalMulticast() ||
|
|
||||||
ifa.IP.IsLinkLocalMulticast() {
|
|
||||||
// remove embedded scope zone ID
|
// remove embedded scope zone ID
|
||||||
ifa.IP[2], ifa.IP[3] = 0, 0
|
ifa.IP[2], ifa.IP[3] = 0, 0
|
||||||
}
|
}
|
||||||
|
ifat = append(ifat, ifa.toAddr())
|
||||||
}
|
}
|
||||||
ifat = append(ifat, ifa.toAddr())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ifat, nil
|
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
|
||||||
|
}
|
||||||
|
49
src/pkg/net/interface_darwin.go
Normal file
49
src/pkg/net/interface_darwin.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// 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
|
||||||
|
}
|
49
src/pkg/net/interface_freebsd.go
Normal file
49
src/pkg/net/interface_freebsd.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// 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
|
||||||
|
}
|
@ -7,6 +7,7 @@
|
|||||||
package net
|
package net
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@ -102,13 +103,13 @@ func linkFlags(rawFlags uint32) Flags {
|
|||||||
// for a specific interface.
|
// for a specific interface.
|
||||||
func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
|
func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
|
||||||
var (
|
var (
|
||||||
ifat4 []Addr
|
|
||||||
ifat6 []Addr
|
|
||||||
tab []byte
|
tab []byte
|
||||||
msgs4 []syscall.NetlinkMessage
|
|
||||||
msgs6 []syscall.NetlinkMessage
|
|
||||||
e int
|
e int
|
||||||
err os.Error
|
err os.Error
|
||||||
|
ifat4 []Addr
|
||||||
|
ifat6 []Addr
|
||||||
|
msgs4 []syscall.NetlinkMessage
|
||||||
|
msgs6 []syscall.NetlinkMessage
|
||||||
)
|
)
|
||||||
|
|
||||||
tab, e = syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_INET)
|
tab, e = syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_INET)
|
||||||
@ -169,17 +170,102 @@ func newAddr(attrs []syscall.NetlinkRouteAttr, family int) []Addr {
|
|||||||
for _, a := range attrs {
|
for _, a := range attrs {
|
||||||
switch a.Attr.Type {
|
switch a.Attr.Type {
|
||||||
case syscall.IFA_ADDRESS:
|
case syscall.IFA_ADDRESS:
|
||||||
ifa := IPAddr{}
|
|
||||||
switch family {
|
switch family {
|
||||||
case syscall.AF_INET:
|
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:
|
case syscall.AF_INET6:
|
||||||
ifa.IP = make(IP, IPv6len)
|
ifa := &IPAddr{IP: make(IP, IPv6len)}
|
||||||
copy(ifa.IP, a.Value[:])
|
copy(ifa.IP, a.Value[:])
|
||||||
|
ifat = append(ifat, ifa.toAddr())
|
||||||
}
|
}
|
||||||
ifat = append(ifat, ifa.toAddr())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ifat
|
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
|
||||||
|
}
|
||||||
|
@ -21,3 +21,10 @@ func interfaceTable(ifindex int) ([]Interface, os.Error) {
|
|||||||
func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
|
func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
|
||||||
return nil, nil
|
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
|
||||||
|
}
|
||||||
|
@ -45,10 +45,17 @@ func TestInterfaces(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Interface.Addrs() failed: %v", err)
|
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)
|
t.Logf("%q: flags %q, ifindex %v, mtu %v\n", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU)
|
||||||
for _, ifa := range ifat {
|
for _, ifa := range ifat {
|
||||||
t.Logf("\tinterface address %q\n", ifa.String())
|
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())
|
t.Logf("\thardware address %q", ifi.HardwareAddr.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,3 +149,10 @@ func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
|
|||||||
}
|
}
|
||||||
return ifat, nil
|
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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user