blob: ef682bd2cd254d95f17ce5d73669f69b5d4850d0 [file] [log] [blame]
Mikio Harad2e5a122012-09-26 21:03:09 +09001// 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// +build darwin freebsd linux netbsd openbsd
6
7package ipv4_test
8
9import (
10 "code.google.com/p/go.net/ipv4"
11 "net"
12 "testing"
13 "time"
14)
15
16// runPayloadTransponder transmits IPv4 datagram payloads to the
17// loopback address or interface and captures the loopback'd datagram
18// payloads.
19func runPayloadTransponder(t *testing.T, c *ipv4.PacketConn, wb []byte, dst net.Addr) {
20 cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
21 rb := make([]byte, 1500)
22 for i, toggle := range []bool{true, false, true} {
23 if err := c.SetControlMessage(cf, toggle); err != nil {
24 t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v", err)
25 }
26 c.SetTOS(i + 1)
27 var ip net.IP
28 switch v := dst.(type) {
29 case *net.UDPAddr:
30 ip = v.IP
31 case *net.IPAddr:
32 ip = v.IP
33 }
34 if ip.IsMulticast() {
35 c.SetMulticastTTL(i + 1)
36 } else {
37 c.SetTTL(i + 1)
38 }
39 c.SetDeadline(time.Now().Add(100 * time.Millisecond))
Mikio Hara0e4f6eb2012-12-21 07:30:42 +090040 if _, err := c.WriteTo(wb, nil, dst); err != nil {
Mikio Hara28323392012-12-21 13:18:56 +090041 t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err)
Mikio Harad2e5a122012-09-26 21:03:09 +090042 }
Mikio Hara0e4f6eb2012-12-21 07:30:42 +090043 _, cm, _, err := c.ReadFrom(rb)
Mikio Harad2e5a122012-09-26 21:03:09 +090044 if err != nil {
Mikio Hara28323392012-12-21 13:18:56 +090045 t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err)
Mikio Harad2e5a122012-09-26 21:03:09 +090046 }
47 t.Logf("rcvd cmsg: %v", cm)
48 }
49}
50
51// runDatagramTransponder transmits ICMP for IPv4 datagrams to the
52// loopback address or interface and captures the response datagrams
53// from the protocol stack within the kernel.
54func runDatagramTransponder(t *testing.T, c *ipv4.RawConn, wb []byte, src, dst net.Addr) {
55 cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
56 rb := make([]byte, ipv4.HeaderLen+len(wb))
57 for i, toggle := range []bool{true, false, true} {
58 if err := c.SetControlMessage(cf, toggle); err != nil {
59 t.Fatalf("ipv4.RawConn.SetControlMessage failed: %v", err)
60 }
61 wh := &ipv4.Header{}
62 wh.Version = ipv4.Version
63 wh.Len = ipv4.HeaderLen
64 wh.TOS = i + 1
65 wh.TotalLen = ipv4.HeaderLen + len(wb)
66 wh.TTL = i + 1
67 wh.Protocol = 1
68 if src != nil {
69 wh.Src = src.(*net.IPAddr).IP
70 }
71 if dst != nil {
72 wh.Dst = dst.(*net.IPAddr).IP
73 }
74 c.SetDeadline(time.Now().Add(100 * time.Millisecond))
Mikio Hara0e4f6eb2012-12-21 07:30:42 +090075 if err := c.WriteTo(wh, wb, nil); err != nil {
Mikio Hara28323392012-12-21 13:18:56 +090076 t.Fatalf("ipv4.RawConn.WriteTo failed: %v", err)
Mikio Harad2e5a122012-09-26 21:03:09 +090077 }
Mikio Hara0e4f6eb2012-12-21 07:30:42 +090078 rh, _, cm, err := c.ReadFrom(rb)
Mikio Harad2e5a122012-09-26 21:03:09 +090079 if err != nil {
Mikio Hara28323392012-12-21 13:18:56 +090080 t.Fatalf("ipv4.RawConn.ReadFrom failed: %v", err)
Mikio Harad2e5a122012-09-26 21:03:09 +090081 }
82 t.Logf("rcvd cmsg: %v", cm.String())
83 t.Logf("rcvd hdr: %v", rh.String())
84 }
85}
86
87func loopbackInterface() *net.Interface {
88 ift, err := net.Interfaces()
89 if err != nil {
90 return nil
91 }
92 for _, ifi := range ift {
93 if ifi.Flags&net.FlagLoopback != 0 {
94 return &ifi
95 }
96 }
97 return nil
98}
99
100func isGoodForMulticast(ifi *net.Interface) (net.IP, bool) {
101 if ifi.Flags&net.FlagUp == 0 {
102 return nil, false
103 }
104 // We need a unicast IPv4 address that can be used to specify
105 // the IPv4 multicast interface.
106 ifat, err := ifi.Addrs()
107 if err != nil {
108 return nil, false
109 }
110 if len(ifat) == 0 {
111 return nil, false
112 }
113 var ip net.IP
114 for _, ifa := range ifat {
115 switch v := ifa.(type) {
116 case *net.IPAddr:
117 ip = v.IP
118 case *net.IPNet:
119 ip = v.IP
120 default:
121 continue
122 }
123 if ip.To4() == nil {
124 ip = nil
125 continue
126 }
127 break
128 }
129 if ip == nil {
130 return nil, false
131 }
132 return ip, true
133}