summaryrefslogtreecommitdiff
path: root/internal/dns/header.go
blob: 3b51f6714e938501a5b69a5f67eb36701d3f4f9d (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
55
56
57
package dns

// https://datatracker.ietf.org/doc/html/rfc5395
type Header struct {
	ID      uint16
	Flags   uint16
	QDCount uint16
	ANCount uint16
	NSCount uint16
	ARCount uint16
}

// https://datatracker.ietf.org/doc/html/rfc2929#section-2
// Flags has 16-bit Field. Each hexadecima value below indicates
// which items are active.
// Example 0 0000 0 0 0 0 000 0 0 000, so if only AA is active, then
// Example 1 0000 0 0 0 0 000 0 0 000, is 0x8000
// Query and Response
func (h *Header) QR() bool { return h.Flags&0x8000 != 0 }

// Opcode has 4-bit (14 -- 11)
func (h *Header) OpCode() uint8 { return uint8((h.Flags >> 11) & 0xF) }

// Authoritative Answer
func (h *Header) AA() bool { return h.Flags&0x0400 != 0 }

// Truncation
func (h *Header) TC() bool { return h.Flags&0x0200 != 0 }

// Recursion Desired
func (h *Header) RD() bool { return h.Flags&0x0100 != 0 }

// Recursion Available
func (h *Header) RA() bool { return h.Flags&0x0080 != 0 }

// Mutator Flags
func (h *Header) SetQR(v bool) { h.set(0x8000, v) }
func (h *Header) SetOpCode(v uint8) {
	h.Flags = (h.Flags &^ (0xF << 11)) |
		((uint16(v) & 0xF) << 11)
}
func (h *Header) SetAA(v bool)     { h.set(0x0400, v) }
func (h *Header) SetTC(v bool)     { h.set(0x0200, v) }
func (h *Header) SetRD(v bool)     { h.set(0x0100, v) }
func (h *Header) SetRA(v bool)     { h.set(0x0080, v) }
func (h *Header) SetZ(v uint8)     { h.Flags = (h.Flags &^ (0x7 << 4)) | ((uint16(v) & 0x7) << 4) }
func (h *Header) SetAD(v bool)     { h.set(0x0020, v) }
func (h *Header) SetCD(v bool)     { h.set(0x0010, v) }
func (h *Header) SetRCode(v uint8) { h.Flags = (h.Flags &^ 0xF) | (uint16(v) & 0xF) }

func (h *Header) set(mask uint16, v bool) {
	if v {
		h.Flags |= mask
	} else {
		h.Flags &^= mask
	}
}