|
|
|
@ -751,6 +751,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)
|
|
|
|
@ -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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|