github.com/roboticscm/goman@v0.0.0-20210203095141-87c07b4a0a55/src/net/interface_freebsd.go (about) 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_IFMALIST, ifi.Index) 16 if err != nil { 17 return nil, os.NewSyscallError("route rib", err) 18 } 19 msgs, err := syscall.ParseRoutingMessage(tab) 20 if err != nil { 21 return nil, os.NewSyscallError("route message", 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 ifmat = append(ifmat, ifma...) 33 } 34 } 35 } 36 return ifmat, nil 37 } 38 39 func newMulticastAddr(ifi *Interface, m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) { 40 sas, err := syscall.ParseRoutingSockaddr(m) 41 if err != nil { 42 return nil, os.NewSyscallError("route sockaddr", err) 43 } 44 var ifmat []Addr 45 for _, sa := range sas { 46 switch sa := sa.(type) { 47 case *syscall.SockaddrInet4: 48 ifma := &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])} 49 ifmat = append(ifmat, ifma.toAddr()) 50 case *syscall.SockaddrInet6: 51 ifma := &IPAddr{IP: make(IP, IPv6len)} 52 copy(ifma.IP, sa.Addr[:]) 53 // NOTE: KAME based IPv6 protocol stack usually embeds 54 // the interface index in the interface-local or link- 55 // local address as the kernel-internal form. 56 if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() { 57 ifma.IP[2], ifma.IP[3] = 0, 0 58 } 59 ifmat = append(ifmat, ifma.toAddr()) 60 } 61 } 62 return ifmat, nil 63 }