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 package net 6 7 import ( 8 "os" 9 "syscall" 10 ) 11 12 // interfaceMulticastAddrTable returns addresses for a specific 13 // interface. 14 func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) { 15 tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST2, ifi.Index) 16 if err != nil { 17 return nil, os.NewSyscallError("routerib", err) 18 } 19 msgs, err := syscall.ParseRoutingMessage(tab) 20 if err != nil { 21 return nil, os.NewSyscallError("parseroutingmessage", err) 22 } 23 var ifmat []Addr 24 for _, m := range msgs { 25 switch m := m.(type) { 26 case *syscall.InterfaceMulticastAddrMessage: 27 if ifi.Index == int(m.Header.Index) { 28 ifma, err := newMulticastAddr(ifi, m) 29 if err != nil { 30 return nil, err 31 } 32 if ifma != nil { 33 ifmat = append(ifmat, ifma) 34 } 35 } 36 } 37 } 38 return ifmat, nil 39 } 40 41 func newMulticastAddr(ifi *Interface, m *syscall.InterfaceMulticastAddrMessage) (*IPAddr, error) { 42 sas, err := syscall.ParseRoutingSockaddr(m) 43 if err != nil { 44 return nil, os.NewSyscallError("parseroutingsockaddr", err) 45 } 46 switch sa := sas[syscall.RTAX_IFA].(type) { 47 case *syscall.SockaddrInet4: 48 return &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])}, nil 49 case *syscall.SockaddrInet6: 50 ifma := IPAddr{IP: make(IP, IPv6len)} 51 copy(ifma.IP, sa.Addr[:]) 52 // NOTE: KAME based IPv6 protcol stack usually embeds 53 // the interface index in the interface-local or 54 // link-local address as the kernel-internal form. 55 if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() { 56 ifma.IP[2], ifma.IP[3] = 0, 0 57 } 58 return &ifma, nil 59 default: 60 return nil, nil 61 } 62 } 63