sys_asmreq.go (2657B)
1 // Copyright 2012 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 //go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd || solaris || windows 6 // +build aix darwin dragonfly freebsd netbsd openbsd solaris windows 7 8 package ipv4 9 10 import ( 11 "errors" 12 "net" 13 "unsafe" 14 15 "golang.org/x/net/internal/socket" 16 ) 17 18 var errNoSuchInterface = errors.New("no such interface") 19 20 func (so *sockOpt) setIPMreq(c *socket.Conn, ifi *net.Interface, grp net.IP) error { 21 mreq := ipMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}} 22 if err := setIPMreqInterface(&mreq, ifi); err != nil { 23 return err 24 } 25 b := (*[sizeofIPMreq]byte)(unsafe.Pointer(&mreq))[:sizeofIPMreq] 26 return so.Set(c, b) 27 } 28 29 func (so *sockOpt) getMulticastIf(c *socket.Conn) (*net.Interface, error) { 30 var b [4]byte 31 if _, err := so.Get(c, b[:]); err != nil { 32 return nil, err 33 } 34 ifi, err := netIP4ToInterface(net.IPv4(b[0], b[1], b[2], b[3])) 35 if err != nil { 36 return nil, err 37 } 38 return ifi, nil 39 } 40 41 func (so *sockOpt) setMulticastIf(c *socket.Conn, ifi *net.Interface) error { 42 ip, err := netInterfaceToIP4(ifi) 43 if err != nil { 44 return err 45 } 46 var b [4]byte 47 copy(b[:], ip) 48 return so.Set(c, b[:]) 49 } 50 51 func setIPMreqInterface(mreq *ipMreq, ifi *net.Interface) error { 52 if ifi == nil { 53 return nil 54 } 55 ifat, err := ifi.Addrs() 56 if err != nil { 57 return err 58 } 59 for _, ifa := range ifat { 60 switch ifa := ifa.(type) { 61 case *net.IPAddr: 62 if ip := ifa.IP.To4(); ip != nil { 63 copy(mreq.Interface[:], ip) 64 return nil 65 } 66 case *net.IPNet: 67 if ip := ifa.IP.To4(); ip != nil { 68 copy(mreq.Interface[:], ip) 69 return nil 70 } 71 } 72 } 73 return errNoSuchInterface 74 } 75 76 func netIP4ToInterface(ip net.IP) (*net.Interface, error) { 77 ift, err := net.Interfaces() 78 if err != nil { 79 return nil, err 80 } 81 for _, ifi := range ift { 82 ifat, err := ifi.Addrs() 83 if err != nil { 84 return nil, err 85 } 86 for _, ifa := range ifat { 87 switch ifa := ifa.(type) { 88 case *net.IPAddr: 89 if ip.Equal(ifa.IP) { 90 return &ifi, nil 91 } 92 case *net.IPNet: 93 if ip.Equal(ifa.IP) { 94 return &ifi, nil 95 } 96 } 97 } 98 } 99 return nil, errNoSuchInterface 100 } 101 102 func netInterfaceToIP4(ifi *net.Interface) (net.IP, error) { 103 if ifi == nil { 104 return net.IPv4zero.To4(), nil 105 } 106 ifat, err := ifi.Addrs() 107 if err != nil { 108 return nil, err 109 } 110 for _, ifa := range ifat { 111 switch ifa := ifa.(type) { 112 case *net.IPAddr: 113 if ip := ifa.IP.To4(); ip != nil { 114 return ip, nil 115 } 116 case *net.IPNet: 117 if ip := ifa.IP.To4(); ip != nil { 118 return ip, nil 119 } 120 } 121 } 122 return nil, errNoSuchInterface 123 }