go test: add ICMP ping

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jonathan Rudenberg 2016-07-06 22:57:08 -04:00 committed by Jason A. Donenfeld
parent 1f349aa101
commit 35a61c32fa

View file

@ -12,6 +12,8 @@ import (
"github.com/dchest/blake2s" "github.com/dchest/blake2s"
"github.com/titanous/noise" "github.com/titanous/noise"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
) )
func main() { func main() {
@ -36,6 +38,7 @@ func main() {
} }
defer conn.Close() defer conn.Close()
// write handshake initiation packet
now := time.Now() now := time.Now()
tai64n := make([]byte, 12) tai64n := make([]byte, 12)
binary.BigEndian.PutUint64(tai64n[:], uint64(now.Unix())) binary.BigEndian.PutUint64(tai64n[:], uint64(now.Unix()))
@ -53,6 +56,7 @@ func main() {
log.Fatalf("error writing initiation packet: %s", err) log.Fatalf("error writing initiation packet: %s", err)
} }
// read handshake response packet
responsePacket := make([]byte, 89) responsePacket := make([]byte, 89)
n, err := conn.Read(responsePacket) n, err := conn.Read(responsePacket)
if err != nil { if err != nil {
@ -69,7 +73,7 @@ func main() {
if ourIndex != 28 { if ourIndex != 28 {
log.Fatalf("response packet index wrong: want %d, got %d", 28, ourIndex) log.Fatalf("response packet index wrong: want %d, got %d", 28, ourIndex)
} }
payload, sendCipher, _, err := hs.ReadMessage(nil, responsePacket[9:57]) payload, sendCipher, receiveCipher, err := hs.ReadMessage(nil, responsePacket[9:57])
if err != nil { if err != nil {
log.Fatalf("error reading handshake message: %s", err) log.Fatalf("error reading handshake message: %s", err)
} }
@ -77,12 +81,64 @@ func main() {
log.Fatalf("unexpected payload: %x", payload) log.Fatalf("unexpected payload: %x", payload)
} }
keepalivePacket := make([]byte, 13) // write ICMP Echo packet
keepalivePacket[0] = 4 // Type: Data pingMessage, _ := (&icmp.Message{
binary.LittleEndian.PutUint32(keepalivePacket[1:], theirIndex) Type: ipv4.ICMPTypeEcho,
binary.LittleEndian.PutUint64(keepalivePacket[5:], 0) // Nonce Body: &icmp.Echo{
keepalivePacket = sendCipher.Encrypt(keepalivePacket, nil, nil) ID: 1,
if _, err := conn.Write(keepalivePacket); err != nil { Seq: 1,
log.Fatalf("error writing keepalive packet: %s", err) Data: []byte("WireGuard"),
},
}).Marshal(nil)
pingHeader, err := (&ipv4.Header{
Version: ipv4.Version,
Len: ipv4.HeaderLen,
TotalLen: ipv4.HeaderLen + len(pingMessage),
Protocol: 1, // ICMP
TTL: 2,
Checksum: 0xa15b, // the packet is always the same, hard-code checksum
Src: net.IPv4(10, 189, 129, 2),
Dst: net.IPv4(10, 189, 129, 1),
}).Marshal()
binary.BigEndian.PutUint16(pingHeader[2:], uint16(ipv4.HeaderLen+len(pingMessage))) // fix the length endianness on BSDs
if err != nil {
panic(err)
}
pingPacket := make([]byte, 13)
pingPacket[0] = 4 // Type: Data
binary.LittleEndian.PutUint32(pingPacket[1:], theirIndex)
binary.LittleEndian.PutUint64(pingPacket[5:], 0) // Nonce
pingPacket = sendCipher.Encrypt(pingPacket, nil, append(pingHeader, pingMessage...))
if _, err := conn.Write(pingPacket); err != nil {
log.Fatalf("error writing ping message: %s", err)
}
// read ICMP Echo Reply packet
replyPacket := make([]byte, 128)
n, err = conn.Read(replyPacket)
if err != nil {
log.Fatalf("error reading ping reply message: %s", err)
}
replyPacket = replyPacket[:n]
if replyPacket[0] != 4 { // Type: Data
log.Fatalf("unexpected reply packet type: %d", replyPacket[0])
}
replyPacket, err = receiveCipher.Decrypt(nil, nil, replyPacket[13:])
if err != nil {
log.Fatalf("error decrypting reply packet: %s", err)
}
replyHeaderLen := int(replyPacket[0]&0x0f) << 2
replyLen := binary.BigEndian.Uint16(replyPacket[2:])
replyMessage, err := icmp.ParseMessage(1, replyPacket[replyHeaderLen:replyLen])
if err != nil {
log.Fatalf("error parsing echo: %s", err)
}
echo, ok := replyMessage.Body.(*icmp.Echo)
if !ok {
log.Fatalf("unexpected reply body type %T", replyMessage.Body)
}
if echo.ID != 1 || echo.Seq != 1 || string(echo.Data) != "WireGuard" {
log.Fatalf("incorrect echo response: %#v", echo)
} }
} }