diff --git a/net/netcheck/netcheck.go b/net/netcheck/netcheck.go index ff6f9ddb7..26c8d118b 100644 --- a/net/netcheck/netcheck.go +++ b/net/netcheck/netcheck.go @@ -751,6 +751,7 @@ func (rs *reportState) probePortMapServices() { 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) @@ -758,17 +759,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 }