From e1e930d1f36a8633663baa6addcd18a32714aef9 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 8 Dec 2020 15:22:26 -0800 Subject: [PATCH] net/netcheck: fix offset of unspecified address in PCP request packet Fixes #810 (cherry picked from commit 08f94b3b504b8b59d0f1c0bbce654e29c55019de) --- net/netcheck/netcheck.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/net/netcheck/netcheck.go b/net/netcheck/netcheck.go index 6bfa34b75..8676a833e 100644 --- a/net/netcheck/netcheck.go +++ b/net/netcheck/netcheck.go @@ -756,6 +756,7 @@ var uPnPPacket = []byte("M-SEARCH * HTTP/1.1\r\n" + var v4unspec, _ = netaddr.ParseIP("0.0.0.0") +// pcpPacket generates a PCP packet with a MAP opcode. func pcpPacket(myIP netaddr.IP, mapToLocalPort int, delete bool) []byte { const udpProtoNumber = 17 lifetimeSeconds := uint32(1) @@ -763,17 +764,24 @@ func pcpPacket(myIP netaddr.IP, mapToLocalPort int, delete bool) []byte { lifetimeSeconds = 0 } const opMap = 1 + + // 24 byte header + 36 byte map opcode pkt := make([]byte, (32+32+128)/8+(96+8+24+16+16+128)/8) + + // The header (https://tools.ietf.org/html/rfc6887#section-7.1) pkt[0] = 2 // version pkt[1] = opMap binary.BigEndian.PutUint32(pkt[4:8], lifetimeSeconds) myIP16 := myIP.As16() copy(pkt[8:], myIP16[:]) - rand.Read(pkt[24 : 24+12]) - pkt[36] = udpProtoNumber - binary.BigEndian.PutUint16(pkt[40:], uint16(mapToLocalPort)) + + // The map opcode body (https://tools.ietf.org/html/rfc6887#section-11.1) + mapOp := pkt[24:] + rand.Read(mapOp[:12]) // 96 bit mappping nonce + mapOp[12] = udpProtoNumber + binary.BigEndian.PutUint16(mapOp[16:], uint16(mapToLocalPort)) v4unspec16 := v4unspec.As16() - copy(pkt[40:], v4unspec16[:]) + copy(mapOp[20:], v4unspec16[:]) return pkt }