a go dns packet parser
at codereview 4.5 kB view raw
1package magna 2 3import ( 4 "encoding/binary" 5 "net" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10) 11 12func TestTXTRecord(t *testing.T) { 13 rdataBytes := []byte{0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'} 14 rdlength := uint16(len(rdataBytes)) 15 16 buf := []byte{0x00} 17 buf = binary.BigEndian.AppendUint16(buf, uint16(TXTType)) 18 buf = binary.BigEndian.AppendUint16(buf, uint16(IN)) 19 buf = binary.BigEndian.AppendUint32(buf, 3600) 20 buf = binary.BigEndian.AppendUint16(buf, rdlength) 21 buf = append(buf, rdataBytes...) 22 23 rr := &ResourceRecord{} 24 offset, err := rr.Decode(buf, 0) 25 require.NoError(t, err) 26 assert.Equal(t, len(buf), offset) 27 require.IsType(t, &TXT{}, rr.RData) 28 29 txtData := rr.RData.(*TXT) 30 31 expectedDecodedData := []string{"abc", "def"} 32 assert.Equal(t, expectedDecodedData, txtData.TxtData, "Decoded TXT data does not match expected concatenation") 33 34 txtToEncode := &TXT{TxtData: []string{"test"}} 35 expectedEncodedRdata := []byte{0x04, 't', 'e', 's', 't'} 36 37 encodeBuf := []byte{} 38 encodedRdata := txtToEncode.Encode(encodeBuf, nil) 39 40 assert.Equal(t, expectedEncodedRdata, encodedRdata, "Encoded TXT RDATA is incorrect") 41} 42 43func TestHINFORecordRFCCompliance(t *testing.T) { 44 rdataBytes := []byte{0x03, 'C', 'P', 'U', 0x02, 'O', 'S'} 45 rdlength := uint16(len(rdataBytes)) 46 47 buf := []byte{0x00} 48 buf = binary.BigEndian.AppendUint16(buf, uint16(HINFOType)) 49 buf = binary.BigEndian.AppendUint16(buf, uint16(IN)) 50 buf = binary.BigEndian.AppendUint32(buf, 3600) 51 buf = binary.BigEndian.AppendUint16(buf, rdlength) 52 buf = append(buf, rdataBytes...) 53 54 rr := &ResourceRecord{} 55 offset, err := rr.Decode(buf, 0) 56 require.NoError(t, err) 57 assert.Equal(t, len(buf), offset) 58 require.IsType(t, &HINFO{}, rr.RData) 59 60 hinfoData := rr.RData.(*HINFO) 61 62 assert.Equal(t, "CPU", hinfoData.CPU, "Decoded HINFO CPU does not match") 63 assert.Equal(t, "OS", hinfoData.OS, "Decoded HINFO OS does not match") 64 65 hinfoToEncode := &HINFO{CPU: "Intel", OS: "Linux"} 66 expectedEncodedRdata := []byte{0x05, 'I', 'n', 't', 'e', 'l', 0x05, 'L', 'i', 'n', 'u', 'x'} 67 encodeBuf := []byte{} 68 encodedRdata := hinfoToEncode.Encode(encodeBuf, nil) 69 70 assert.Equal(t, expectedEncodedRdata, encodedRdata, "Encoded HINFO RDATA is incorrect") 71} 72 73func TestWKSRecordDecoding(t *testing.T) { 74 addr := net.ParseIP("192.168.1.1").To4() 75 proto := byte(6) 76 bitmap := []byte{0x01, 0x80} 77 rdataBytes := append(addr, proto) 78 rdataBytes = append(rdataBytes, bitmap...) 79 rdlength := uint16(len(rdataBytes)) 80 81 buf := []byte{0x00} 82 buf = binary.BigEndian.AppendUint16(buf, uint16(WKSType)) 83 buf = binary.BigEndian.AppendUint16(buf, uint16(IN)) 84 buf = binary.BigEndian.AppendUint32(buf, 3600) 85 buf = binary.BigEndian.AppendUint16(buf, rdlength) 86 buf = append(buf, rdataBytes...) 87 88 rr := &ResourceRecord{} 89 offset, err := rr.Decode(buf, 0) 90 require.NoError(t, err) 91 assert.Equal(t, len(buf), offset) 92 require.IsType(t, &WKS{}, rr.RData) 93 94 wksData := rr.RData.(*WKS) 95 96 assert.Equal(t, addr, wksData.Address.To4()) 97 assert.Equal(t, proto, wksData.Protocol) 98 assert.Equal(t, bitmap, wksData.BitMap) 99} 100 101func TestSOADecodeWithCompression(t *testing.T) { 102 input := []byte{0x69, 0x7b, 0x81, 0x83, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0xf, 0x6e, 0x6f, 0x77, 0x61, 0x79, 0x74, 0x68, 0x69, 0x73, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x3, 0x63, 0x6f, 0x6d, 0x0, 0x0, 0x1, 0x0, 0x1, 0xc0, 0x1c, 0x0, 0x6, 0x0, 0x1, 0x0, 0x0, 0x3, 0x84, 0x0, 0x3d, 0x1, 0x61, 0xc, 0x67, 0x74, 0x6c, 0x64, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x3, 0x6e, 0x65, 0x74, 0x0, 0x5, 0x6e, 0x73, 0x74, 0x6c, 0x64, 0xc, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2d, 0x67, 0x72, 0x73, 0xc0, 0x1c, 0x67, 0xaa, 0xc5, 0x6b, 0x0, 0x0, 0x7, 0x8, 0x0, 0x0, 0x3, 0x84, 0x0, 0x9, 0x3a, 0x80, 0x0, 0x0, 0x3, 0x84} 103 104 msg := &Message{} 105 err := msg.Decode(input) 106 assert.NoError(t, err) 107 108 assert.Equal(t, 1, len(msg.Authority)) 109 110 rr := msg.Authority[0] 111 assert.Equal(t, DNSType(6), rr.RType) 112 assert.Equal(t, DNSClass(1), rr.RClass) 113 assert.Equal(t, uint32(900), rr.TTL) 114 assert.Equal(t, uint16(61), rr.RDLength) 115 116 soa, ok := msg.Authority[0].RData.(*SOA) 117 assert.True(t, ok) 118 119 assert.Equal(t, "a.gtld-servers.net", soa.MName) 120 assert.Equal(t, "nstld.verisign-grs.com", soa.RName) 121 assert.Equal(t, uint32(1739244907), soa.Serial) 122 assert.Equal(t, uint32(1800), soa.Refresh) 123 assert.Equal(t, uint32(900), soa.Retry) 124 assert.Equal(t, uint32(604800), soa.Expire) 125 assert.Equal(t, uint32(900), soa.Minimum) 126 127 encoded := msg.Encode() 128 assert.Equal(t, input, encoded) 129}