2
2
// Use of this source code is governed by a BSD-style
3
3
// license that can be found in the LICENSE file.
4
4
5
- // +build darwin freebsd linux netbsd openbsd
6
-
7
5
package ipv4_test
8
6
9
7
import (
10
8
"code.google.com/p/go.net/ipv4"
11
9
"net"
12
10
"os"
11
+ "runtime"
13
12
"testing"
13
+ "time"
14
14
)
15
15
16
- func TestReadWriteMulticastIPPayloadUDP (t * testing.T ) {
17
- if testing .Short () || ! * testExternal {
18
- t .Skip ("to avoid external network" )
16
+ func TestPacketConnReadWriteMulticastUDP (t * testing.T ) {
17
+ switch runtime .GOOS {
18
+ case "plan9" , "windows" :
19
+ t .Skipf ("not supported on %q" , runtime .GOOS )
20
+ }
21
+ ifi := loopbackInterface ()
22
+ if ifi == nil {
23
+ t .Skipf ("not available on %q" , runtime .GOOS )
19
24
}
20
25
21
- c , err := net .ListenPacket ("udp4" , "224.0.0.0:1024 " ) // see RFC 4727
26
+ c , err := net .ListenPacket ("udp4" , "224.0.0.0:0 " ) // see RFC 4727
22
27
if err != nil {
23
28
t .Fatalf ("net.ListenPacket failed: %v" , err )
24
29
}
25
30
defer c .Close ()
26
31
27
- ifi := loopbackInterface ( )
28
- if ifi = = nil {
29
- t .Skip ( "an appropriate interface not found" )
32
+ _ , port , err := net . SplitHostPort ( c . LocalAddr (). String () )
33
+ if err ! = nil {
34
+ t .Fatalf ( "net.SplitHostPort failed: %v" , err )
30
35
}
31
- dst , err := net .ResolveUDPAddr ("udp4" , "224.0.0.254:1024" ) // see RFC 4727
36
+ dst , err := net .ResolveUDPAddr ("udp4" , "224.0.0.254:" + port ) // see RFC 4727
32
37
if err != nil {
33
38
t .Fatalf ("net.ResolveUDPAddr failed: %v" , err )
34
39
}
35
40
36
41
p := ipv4 .NewPacketConn (c )
42
+ defer p .Close ()
37
43
if err := p .JoinGroup (ifi , dst ); err != nil {
38
44
t .Fatalf ("ipv4.PacketConn.JoinGroup on %v failed: %v" , ifi , err )
39
45
}
40
46
if err := p .SetMulticastInterface (ifi ); err != nil {
41
47
t .Fatalf ("ipv4.PacketConn.SetMulticastInterface failed: %v" , err )
42
48
}
49
+ if _ , err := p .MulticastInterface (); err != nil {
50
+ t .Fatalf ("ipv4.PacketConn.MulticastInterface failed: %v" , err )
51
+ }
43
52
if err := p .SetMulticastLoopback (true ); err != nil {
44
53
t .Fatalf ("ipv4.PacketConn.SetMulticastLoopback failed: %v" , err )
45
54
}
55
+ if _ , err := p .MulticastLoopback (); err != nil {
56
+ t .Fatalf ("ipv4.PacketConn.MulticastLoopback failed: %v" , err )
57
+ }
46
58
cf := ipv4 .FlagTTL | ipv4 .FlagDst | ipv4 .FlagInterface
59
+
47
60
for i , toggle := range []bool {true , false , true } {
48
61
if err := p .SetControlMessage (cf , toggle ); err != nil {
49
62
t .Fatalf ("ipv4.PacketConn.SetControlMessage failed: %v" , err )
50
63
}
51
- writeThenReadPayload (t , i , p , []byte ("HELLO-R-U-THERE" ), dst )
64
+ if err := p .SetDeadline (time .Now ().Add (200 * time .Millisecond )); err != nil {
65
+ t .Fatalf ("ipv4.PacketConn.SetDeadline failed: %v" , err )
66
+ }
67
+ p .SetMulticastTTL (i + 1 )
68
+ if _ , err := p .WriteTo ([]byte ("HELLO-R-U-THERE" ), nil , dst ); err != nil {
69
+ t .Fatalf ("ipv4.PacketConn.WriteTo failed: %v" , err )
70
+ }
71
+ b := make ([]byte , 128 )
72
+ if _ , cm , _ , err := p .ReadFrom (b ); err != nil {
73
+ t .Fatalf ("ipv4.PacketConn.ReadFrom failed: %v" , err )
74
+ } else {
75
+ t .Logf ("rcvd cmsg: %v" , cm )
76
+ }
52
77
}
53
78
}
54
79
55
- func TestReadWriteMulticastIPPayloadICMP (t * testing.T ) {
56
- if testing .Short () || ! * testExternal {
57
- t .Skip ("to avoid external network" )
80
+ func TestPacketConnReadWriteMulticastICMP (t * testing.T ) {
81
+ switch runtime .GOOS {
82
+ case "plan9" , "windows" :
83
+ t .Skipf ("not supported on %q" , runtime .GOOS )
58
84
}
59
85
if os .Getuid () != 0 {
60
86
t .Skip ("must be root" )
61
87
}
88
+ ifi := loopbackInterface ()
89
+ if ifi == nil {
90
+ t .Skipf ("not available on %q" , runtime .GOOS )
91
+ }
62
92
63
93
c , err := net .ListenPacket ("ip4:icmp" , "0.0.0.0" )
64
94
if err != nil {
65
95
t .Fatalf ("net.ListenPacket failed: %v" , err )
66
96
}
67
97
defer c .Close ()
68
98
69
- ifi := loopbackInterface ()
70
- if ifi == nil {
71
- t .Skip ("an appropriate interface not found" )
72
- }
73
99
dst , err := net .ResolveIPAddr ("ip4" , "224.0.0.254" ) // see RFC 4727
74
100
if err != nil {
75
101
t .Fatalf ("net.ResolveIPAddr failed: %v" , err )
76
102
}
77
103
78
104
p := ipv4 .NewPacketConn (c )
105
+ defer p .Close ()
79
106
if err := p .JoinGroup (ifi , dst ); err != nil {
80
107
t .Fatalf ("ipv4.PacketConn.JoinGroup on %v failed: %v" , ifi , err )
81
108
}
82
109
if err := p .SetMulticastInterface (ifi ); err != nil {
83
110
t .Fatalf ("ipv4.PacketConn.SetMulticastInterface failed: %v" , err )
84
111
}
112
+ if _ , err := p .MulticastInterface (); err != nil {
113
+ t .Fatalf ("ipv4.PacketConn.MulticastInterface failed: %v" , err )
114
+ }
115
+ if err := p .SetMulticastLoopback (true ); err != nil {
116
+ t .Fatalf ("ipv4.PacketConn.SetMulticastLoopback failed: %v" , err )
117
+ }
118
+ if _ , err := p .MulticastLoopback (); err != nil {
119
+ t .Fatalf ("ipv4.PacketConn.MulticastLoopback failed: %v" , err )
120
+ }
85
121
cf := ipv4 .FlagTTL | ipv4 .FlagDst | ipv4 .FlagInterface
122
+
86
123
for i , toggle := range []bool {true , false , true } {
87
124
wb , err := (& icmpMessage {
88
125
Type : ipv4 .ICMPTypeEcho , Code : 0 ,
@@ -97,35 +134,50 @@ func TestReadWriteMulticastIPPayloadICMP(t *testing.T) {
97
134
if err := p .SetControlMessage (cf , toggle ); err != nil {
98
135
t .Fatalf ("ipv4.PacketConn.SetControlMessage failed: %v" , err )
99
136
}
100
- rb := writeThenReadPayload (t , i , p , wb , dst )
101
- m , err := parseICMPMessage (rb )
102
- if err != nil {
103
- t .Fatalf ("parseICMPMessage failed: %v" , err )
137
+ if err := p .SetDeadline (time .Now ().Add (200 * time .Millisecond )); err != nil {
138
+ t .Fatalf ("ipv4.PacketConn.SetDeadline failed: %v" , err )
139
+ }
140
+ p .SetMulticastTTL (i + 1 )
141
+ if _ , err := p .WriteTo (wb , nil , dst ); err != nil {
142
+ t .Fatalf ("ipv4.PacketConn.WriteTo failed: %v" , err )
104
143
}
105
- if m .Type != ipv4 .ICMPTypeEchoReply || m .Code != 0 {
106
- t .Fatalf ("got type=%v, code=%v; expected type=%v, code=%v" , m .Type , m .Code , ipv4 .ICMPTypeEchoReply , 0 )
144
+ b := make ([]byte , 128 )
145
+ if n , cm , _ , err := p .ReadFrom (b ); err != nil {
146
+ t .Fatalf ("ipv4.PacketConn.ReadFrom failed: %v" , err )
147
+ } else {
148
+ t .Logf ("rcvd cmsg: %v" , cm )
149
+ m , err := parseICMPMessage (b [:n ])
150
+ if err != nil {
151
+ t .Fatalf ("parseICMPMessage failed: %v" , err )
152
+ }
153
+ switch {
154
+ case m .Type == ipv4 .ICMPTypeEchoReply && m .Code == 0 : // net.inet.icmp.bmcastecho=1
155
+ case m .Type == ipv4 .ICMPTypeEcho && m .Code == 0 : // net.inet.icmp.bmcastecho=0
156
+ default :
157
+ t .Fatalf ("got type=%v, code=%v; expected type=%v, code=%v" , m .Type , m .Code , ipv4 .ICMPTypeEchoReply , 0 )
158
+ }
107
159
}
108
160
}
109
161
}
110
162
111
- func TestReadWriteMulticastIPDatagram (t * testing.T ) {
163
+ func TestRawConnReadWriteMulticastICMP (t * testing.T ) {
112
164
if testing .Short () || ! * testExternal {
113
165
t .Skip ("to avoid external network" )
114
166
}
115
167
if os .Getuid () != 0 {
116
168
t .Skip ("must be root" )
117
169
}
170
+ ifi := loopbackInterface ()
171
+ if ifi == nil {
172
+ t .Skipf ("not available on %q" , runtime .GOOS )
173
+ }
118
174
119
175
c , err := net .ListenPacket ("ip4:icmp" , "0.0.0.0" )
120
176
if err != nil {
121
177
t .Fatalf ("net.ListenPacket failed: %v" , err )
122
178
}
123
179
defer c .Close ()
124
180
125
- ifi := loopbackInterface ()
126
- if ifi == nil {
127
- t .Skip ("an appropriate interface not found" )
128
- }
129
181
dst , err := net .ResolveIPAddr ("ip4" , "224.0.0.254" ) // see RFC 4727
130
182
if err != nil {
131
183
t .Fatalf ("ResolveIPAddr failed: %v" , err )
@@ -135,13 +187,24 @@ func TestReadWriteMulticastIPDatagram(t *testing.T) {
135
187
if err != nil {
136
188
t .Fatalf ("ipv4.NewRawConn failed: %v" , err )
137
189
}
190
+ defer r .Close ()
138
191
if err := r .JoinGroup (ifi , dst ); err != nil {
139
192
t .Fatalf ("ipv4.RawConn.JoinGroup on %v failed: %v" , ifi , err )
140
193
}
141
194
if err := r .SetMulticastInterface (ifi ); err != nil {
142
- t .Fatalf ("ipv4.PacketConn.SetMulticastInterface failed: %v" , err )
195
+ t .Fatalf ("ipv4.RawConn.SetMulticastInterface failed: %v" , err )
196
+ }
197
+ if _ , err := r .MulticastInterface (); err != nil {
198
+ t .Fatalf ("ipv4.RawConn.MulticastInterface failed: %v" , err )
199
+ }
200
+ if err := r .SetMulticastLoopback (true ); err != nil {
201
+ t .Fatalf ("ipv4.RawConn.SetMulticastLoopback failed: %v" , err )
202
+ }
203
+ if _ , err := r .MulticastLoopback (); err != nil {
204
+ t .Fatalf ("ipv4.RawConn.MulticastLoopback failed: %v" , err )
143
205
}
144
206
cf := ipv4 .FlagTTL | ipv4 .FlagDst | ipv4 .FlagInterface
207
+
145
208
for i , toggle := range []bool {true , false , true } {
146
209
wb , err := (& icmpMessage {
147
210
Type : ipv4 .ICMPTypeEcho , Code : 0 ,
@@ -153,16 +216,39 @@ func TestReadWriteMulticastIPDatagram(t *testing.T) {
153
216
if err != nil {
154
217
t .Fatalf ("icmpMessage.Marshal failed: %v" , err )
155
218
}
219
+ wh := & ipv4.Header {
220
+ Version : ipv4 .Version ,
221
+ Len : ipv4 .HeaderLen ,
222
+ TOS : i + 1 ,
223
+ TotalLen : ipv4 .HeaderLen + len (wb ),
224
+ Protocol : 1 ,
225
+ Dst : dst .IP ,
226
+ }
156
227
if err := r .SetControlMessage (cf , toggle ); err != nil {
157
228
t .Fatalf ("ipv4.RawConn.SetControlMessage failed: %v" , err )
158
229
}
159
- rb := writeThenReadDatagram (t , i , r , wb , nil , dst )
160
- m , err := parseICMPMessage (rb )
161
- if err != nil {
162
- t .Fatalf ("parseICMPMessage failed: %v" , err )
230
+ if err := r .SetDeadline (time .Now ().Add (200 * time .Millisecond )); err != nil {
231
+ t .Fatalf ("ipv4.RawConn.SetDeadline failed: %v" , err )
232
+ }
233
+ r .SetMulticastTTL (i + 1 )
234
+ if err := r .WriteTo (wh , wb , nil ); err != nil {
235
+ t .Fatalf ("ipv4.RawConn.WriteTo failed: %v" , err )
163
236
}
164
- if m .Type != ipv4 .ICMPTypeEchoReply || m .Code != 0 {
165
- t .Fatalf ("got type=%v, code=%v; expected type=%v, code=%v" , m .Type , m .Code , ipv4 .ICMPTypeEchoReply , 0 )
237
+ rb := make ([]byte , ipv4 .HeaderLen + 128 )
238
+ if rh , b , cm , err := r .ReadFrom (rb ); err != nil {
239
+ t .Fatalf ("ipv4.RawConn.ReadFrom failed: %v" , err )
240
+ } else {
241
+ t .Logf ("rcvd cmsg: %v" , cm )
242
+ m , err := parseICMPMessage (b )
243
+ if err != nil {
244
+ t .Fatalf ("parseICMPMessage failed: %v" , err )
245
+ }
246
+ switch {
247
+ case isUnicast (rh .Dst ) && m .Type == ipv4 .ICMPTypeEchoReply && m .Code == 0 : // net.inet.icmp.bmcastecho=1
248
+ case rh .Dst .IsMulticast () && m .Type == ipv4 .ICMPTypeEcho && m .Code == 0 : // net.inet.icmp.bmcastecho=0
249
+ default :
250
+ t .Fatalf ("got type=%v, code=%v; expected type=%v, code=%v" , m .Type , m .Code , ipv4 .ICMPTypeEchoReply , 0 )
251
+ }
166
252
}
167
253
}
168
254
}
0 commit comments