OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [net/] [ipraw_test.go] - Blame information for rev 749

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2009 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
        "bytes"
9
        "os"
10
        "testing"
11
        "time"
12
)
13
 
14
var icmpTests = []struct {
15
        net   string
16
        laddr string
17
        raddr string
18
        ipv6  bool
19
}{
20
        {"ip4:icmp", "", "127.0.0.1", false},
21
        {"ip6:icmp", "", "::1", true},
22
}
23
 
24
func TestICMP(t *testing.T) {
25
        if os.Getuid() != 0 {
26
                t.Logf("test disabled; must be root")
27
                return
28
        }
29
 
30
        seqnum := 61455
31
        for _, tt := range icmpTests {
32
                if tt.ipv6 && !supportsIPv6 {
33
                        continue
34
                }
35
                id := os.Getpid() & 0xffff
36
                seqnum++
37
                echo := newICMPEchoRequest(tt.ipv6, id, seqnum, 128, []byte("Go Go Gadget Ping!!!"))
38
                exchangeICMPEcho(t, tt.net, tt.laddr, tt.raddr, tt.ipv6, echo)
39
        }
40
}
41
 
42
func exchangeICMPEcho(t *testing.T, net, laddr, raddr string, ipv6 bool, echo []byte) {
43
        c, err := ListenPacket(net, laddr)
44
        if err != nil {
45
                t.Errorf("ListenPacket(%#q, %#q) failed: %v", net, laddr, err)
46
                return
47
        }
48
        c.SetDeadline(time.Now().Add(100 * time.Millisecond))
49
        defer c.Close()
50
 
51
        ra, err := ResolveIPAddr(net, raddr)
52
        if err != nil {
53
                t.Errorf("ResolveIPAddr(%#q, %#q) failed: %v", net, raddr, err)
54
                return
55
        }
56
 
57
        waitForReady := make(chan bool)
58
        go icmpEchoTransponder(t, net, raddr, ipv6, waitForReady)
59
        <-waitForReady
60
 
61
        _, err = c.WriteTo(echo, ra)
62
        if err != nil {
63
                t.Errorf("WriteTo failed: %v", err)
64
                return
65
        }
66
 
67
        reply := make([]byte, 256)
68
        for {
69
                _, _, err := c.ReadFrom(reply)
70
                if err != nil {
71
                        t.Errorf("ReadFrom failed: %v", err)
72
                        return
73
                }
74
                if !ipv6 && reply[0] != ICMP4_ECHO_REPLY {
75
                        continue
76
                }
77
                if ipv6 && reply[0] != ICMP6_ECHO_REPLY {
78
                        continue
79
                }
80
                xid, xseqnum := parseICMPEchoReply(echo)
81
                rid, rseqnum := parseICMPEchoReply(reply)
82
                if rid != xid || rseqnum != xseqnum {
83
                        t.Errorf("ID = %v, Seqnum = %v, want ID = %v, Seqnum = %v", rid, rseqnum, xid, xseqnum)
84
                        return
85
                }
86
                break
87
        }
88
}
89
 
90
func icmpEchoTransponder(t *testing.T, net, raddr string, ipv6 bool, waitForReady chan bool) {
91
        c, err := Dial(net, raddr)
92
        if err != nil {
93
                waitForReady <- true
94
                t.Errorf("Dial(%#q, %#q) failed: %v", net, raddr, err)
95
                return
96
        }
97
        c.SetDeadline(time.Now().Add(100 * time.Millisecond))
98
        defer c.Close()
99
        waitForReady <- true
100
 
101
        echo := make([]byte, 256)
102
        var nr int
103
        for {
104
                nr, err = c.Read(echo)
105
                if err != nil {
106
                        t.Errorf("Read failed: %v", err)
107
                        return
108
                }
109
                if !ipv6 && echo[0] != ICMP4_ECHO_REQUEST {
110
                        continue
111
                }
112
                if ipv6 && echo[0] != ICMP6_ECHO_REQUEST {
113
                        continue
114
                }
115
                break
116
        }
117
 
118
        if !ipv6 {
119
                echo[0] = ICMP4_ECHO_REPLY
120
        } else {
121
                echo[0] = ICMP6_ECHO_REPLY
122
        }
123
 
124
        _, err = c.Write(echo[:nr])
125
        if err != nil {
126
                t.Errorf("Write failed: %v", err)
127
                return
128
        }
129
}
130
 
131
const (
132
        ICMP4_ECHO_REQUEST = 8
133
        ICMP4_ECHO_REPLY   = 0
134
        ICMP6_ECHO_REQUEST = 128
135
        ICMP6_ECHO_REPLY   = 129
136
)
137
 
138
func newICMPEchoRequest(ipv6 bool, id, seqnum, msglen int, filler []byte) []byte {
139
        if !ipv6 {
140
                return newICMPv4EchoRequest(id, seqnum, msglen, filler)
141
        }
142
        return newICMPv6EchoRequest(id, seqnum, msglen, filler)
143
}
144
 
145
func newICMPv4EchoRequest(id, seqnum, msglen int, filler []byte) []byte {
146
        b := newICMPInfoMessage(id, seqnum, msglen, filler)
147
        b[0] = ICMP4_ECHO_REQUEST
148
 
149
        // calculate ICMP checksum
150
        cklen := len(b)
151
        s := uint32(0)
152
        for i := 0; i < cklen-1; i += 2 {
153
                s += uint32(b[i+1])<<8 | uint32(b[i])
154
        }
155
        if cklen&1 == 1 {
156
                s += uint32(b[cklen-1])
157
        }
158
        s = (s >> 16) + (s & 0xffff)
159
        s = s + (s >> 16)
160
        // place checksum back in header; using ^= avoids the
161
        // assumption the checksum bytes are zero
162
        b[2] ^= uint8(^s & 0xff)
163
        b[3] ^= uint8(^s >> 8)
164
 
165
        return b
166
}
167
 
168
func newICMPv6EchoRequest(id, seqnum, msglen int, filler []byte) []byte {
169
        b := newICMPInfoMessage(id, seqnum, msglen, filler)
170
        b[0] = ICMP6_ECHO_REQUEST
171
        return b
172
}
173
 
174
func newICMPInfoMessage(id, seqnum, msglen int, filler []byte) []byte {
175
        b := make([]byte, msglen)
176
        copy(b[8:], bytes.Repeat(filler, (msglen-8)/len(filler)+1))
177
        b[0] = 0                    // type
178
        b[1] = 0                    // code
179
        b[2] = 0                    // checksum
180
        b[3] = 0                    // checksum
181
        b[4] = uint8(id >> 8)       // identifier
182
        b[5] = uint8(id & 0xff)     // identifier
183
        b[6] = uint8(seqnum >> 8)   // sequence number
184
        b[7] = uint8(seqnum & 0xff) // sequence number
185
        return b
186
}
187
 
188
func parseICMPEchoReply(b []byte) (id, seqnum int) {
189
        id = int(b[4])<<8 | int(b[5])
190
        seqnum = int(b[6])<<8 | int(b[7])
191
        return
192
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.