summaryrefslogtreecommitdiffhomepage
path: root/net/packet/udp6.go
blob: 8d7f380884cbbe91a27e74e77ba4fc5a886d84aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause

package packet

import (
	"encoding/binary"

	"tailscale.com/types/ipproto"
)

// UDP6Header is an IPv6+UDP header.
type UDP6Header struct {
	IP6Header
	SrcPort uint16
	DstPort uint16
}

// Len implements Header.
func (h UDP6Header) Len() int {
	return h.IP6Header.Len() + udpHeaderLength
}

// Marshal implements Header.
func (h UDP6Header) Marshal(buf []byte) error {
	if len(buf) < h.Len() {
		return errSmallBuffer
	}
	if len(buf) > maxPacketLength {
		return errLargePacket
	}
	// The caller does not need to set this.
	h.IPProto = ipproto.UDP

	length := len(buf) - h.IP6Header.Len()
	binary.BigEndian.PutUint16(buf[40:42], h.SrcPort)
	binary.BigEndian.PutUint16(buf[42:44], h.DstPort)
	binary.BigEndian.PutUint16(buf[44:46], uint16(length))
	binary.BigEndian.PutUint16(buf[46:48], 0) // blank checksum

	// UDP checksum with IP pseudo header.
	h.IP6Header.marshalPseudo(buf, ipproto.UDP)
	binary.BigEndian.PutUint16(buf[46:48], ip4Checksum(buf[:]))

	h.IP6Header.Marshal(buf)

	return nil
}

// ToResponse implements Header.
func (h *UDP6Header) ToResponse() {
	h.SrcPort, h.DstPort = h.DstPort, h.SrcPort
	h.IP6Header.ToResponse()
}