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