a go dns packet parser
1package magna 2 3import ( 4 "encoding/binary" 5 "fmt" 6) 7 8// Decode decodes the header from the bytes. 9func (h *Header) Decode(buf []byte, offset int) (int, error) { 10 var err error 11 h.ID, offset, err = getU16(buf, offset) 12 if err != nil { 13 return len(buf), fmt.Errorf("header decode: failed to read ID: %w", err) 14 } 15 16 flags, offset, err := getU16(buf, offset) 17 if err != nil { 18 return len(buf), fmt.Errorf("header decode: failed to read flags: %w", err) 19 } 20 21 h.QDCount, offset, err = getU16(buf, offset) 22 if err != nil { 23 return len(buf), fmt.Errorf("header decode: failed to read QDCount: %w", err) 24 } 25 26 h.ANCount, offset, err = getU16(buf, offset) 27 if err != nil { 28 return len(buf), fmt.Errorf("header decode: failed to read ANCount: %w", err) 29 } 30 31 h.NSCount, offset, err = getU16(buf, offset) 32 if err != nil { 33 return len(buf), fmt.Errorf("header decode: failed to read NSCount: %w", err) 34 } 35 36 h.ARCount, offset, err = getU16(buf, offset) 37 if err != nil { 38 return len(buf), fmt.Errorf("header decode: failed to read ARCount: %w", err) 39 } 40 41 h.QR = ((flags >> 15) & 0x01) == 1 42 h.OPCode = OPCode((flags >> 11) & 0x0F) 43 h.AA = ((flags >> 10) & 0x01) == 1 44 h.TC = ((flags >> 9) & 0x01) == 1 45 h.RD = ((flags >> 8) & 0x01) == 1 46 h.RA = ((flags >> 7) & 0x01) == 1 47 h.Z = uint8((flags >> 4) & 0x07) 48 h.RCode = RCode((flags & 0x0F)) 49 50 return offset, nil 51} 52 53// Encode encodes the header packet to the byte representation. 54func (h *Header) Encode() []byte { 55 bytes := make([]byte, 0, 12) 56 57 bytes = binary.BigEndian.AppendUint16(bytes, h.ID) 58 59 var flags uint16 60 if h.QR { 61 flags |= 1 << 15 62 } 63 64 flags |= uint16(h.OPCode) << 11 65 66 if h.AA { 67 flags |= 1 << 10 68 } 69 70 if h.TC { 71 flags |= 1 << 9 72 } 73 74 if h.RD { 75 flags |= 1 << 8 76 } 77 78 if h.RA { 79 flags |= 1 << 7 80 } 81 82 flags |= uint16(h.Z) << 4 83 flags |= uint16(h.RCode) 84 85 bytes = binary.BigEndian.AppendUint16(bytes, flags) 86 bytes = binary.BigEndian.AppendUint16(bytes, h.QDCount) 87 bytes = binary.BigEndian.AppendUint16(bytes, h.ANCount) 88 bytes = binary.BigEndian.AppendUint16(bytes, h.NSCount) 89 bytes = binary.BigEndian.AppendUint16(bytes, h.ARCount) 90 91 return bytes 92}