Skip to content

Commit b9669b7

Browse files
tqbfzx2c4
authored andcommitted
tun/netstack: implement ICMP ping
Provide a PacketConn interface for netstack's ICMP endpoint; netstack currently only provides EchoRequest/EchoResponse ICMP support, so this code exposes only an interface for doing ping. Signed-off-by: Thomas Ptacek <[email protected]> [Jason: rework structure, match std go interfaces, add example code] Signed-off-by: Jason A. Donenfeld <[email protected]>
1 parent e0b8f11 commit b9669b7

File tree

2 files changed

+343
-24
lines changed

2 files changed

+343
-24
lines changed

tun/netstack/examples/ping_client.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//go:build ignore
2+
// +build ignore
3+
4+
/* SPDX-License-Identifier: MIT
5+
*
6+
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
7+
*/
8+
9+
package main
10+
11+
import (
12+
"bytes"
13+
"log"
14+
"math/rand"
15+
"time"
16+
17+
"golang.org/x/net/icmp"
18+
"golang.org/x/net/ipv4"
19+
20+
"golang.zx2c4.com/go118/netip"
21+
"golang.zx2c4.com/wireguard/conn"
22+
"golang.zx2c4.com/wireguard/device"
23+
"golang.zx2c4.com/wireguard/tun/netstack"
24+
)
25+
26+
func main() {
27+
tun, tnet, err := netstack.CreateNetTUN(
28+
[]netip.Addr{netip.MustParseAddr("192.168.4.29")},
29+
[]netip.Addr{netip.MustParseAddr("8.8.8.8")},
30+
1420)
31+
if err != nil {
32+
log.Panic(err)
33+
}
34+
dev := device.NewDevice(tun, conn.NewDefaultBind(), device.NewLogger(device.LogLevelVerbose, ""))
35+
dev.IpcSet(`private_key=a8dac1d8a70a751f0f699fb14ba1cff7b79cf4fbd8f09f44c6e6a90d0369604f
36+
public_key=25123c5dcd3328ff645e4f2a3fce0d754400d3887a0cb7c56f0267e20fbf3c5b
37+
endpoint=163.172.161.0:12912
38+
allowed_ip=0.0.0.0/0
39+
`)
40+
err = dev.Up()
41+
if err != nil {
42+
log.Panic(err)
43+
}
44+
45+
socket, err := tnet.Dial("ping4", "zx2c4.com")
46+
if err != nil {
47+
log.Panic(err)
48+
}
49+
requestPing := icmp.Echo{
50+
Seq: rand.Intn(1 << 16),
51+
Data: []byte("gopher burrow"),
52+
}
53+
icmpBytes, _ := (&icmp.Message{Type: ipv4.ICMPTypeEcho, Code: 0, Body: &requestPing}).Marshal(nil)
54+
socket.SetReadDeadline(time.Now().Add(time.Second * 10))
55+
start := time.Now()
56+
_, err = socket.Write(icmpBytes)
57+
if err != nil {
58+
log.Panic(err)
59+
}
60+
n, err := socket.Read(icmpBytes[:])
61+
if err != nil {
62+
log.Panic(err)
63+
}
64+
replyPacket, err := icmp.ParseMessage(1, icmpBytes[:n])
65+
if err != nil {
66+
log.Panic(err)
67+
}
68+
replyPing, ok := replyPacket.Body.(*icmp.Echo)
69+
if !ok {
70+
log.Panicf("invalid reply type: %v", replyPacket)
71+
}
72+
if !bytes.Equal(replyPing.Data, requestPing.Data) || replyPing.Seq != requestPing.Seq {
73+
log.Panicf("invalid ping reply: %v", replyPing)
74+
}
75+
log.Printf("Ping latency: %v", time.Since(start))
76+
}

0 commit comments

Comments
 (0)