a go dns packet parser
1package magna 2 3import ( 4 "testing" 5 6 "github.com/stretchr/testify/assert" 7) 8 9func TestDecodeDomain(t *testing.T) { 10 tests := []struct { 11 name string 12 offset int 13 input []byte 14 expectedDomain string 15 expectedOffset int 16 expectedError error 17 }{ 18 { 19 name: "Simple domain", 20 input: []byte{3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0}, 21 expectedDomain: "www.example.com", 22 expectedOffset: 17, 23 expectedError: nil, 24 }, 25 { 26 name: "Domain with compression", 27 offset: 17, 28 input: []byte{3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0, 3, 'f', 'o', 'o', 0xC0, 0}, 29 expectedDomain: "foo.www.example.com", 30 expectedOffset: 23, 31 expectedError: nil, 32 }, 33 { 34 name: "Invalid label length", 35 input: []byte{64, 'x'}, 36 expectedDomain: "", 37 expectedOffset: 2, 38 expectedError: &InvalidLabelError{Length: 64}, 39 }, 40 { 41 name: "Compression loop", 42 input: []byte{0xC0, 0, 0xC0, 0}, 43 expectedDomain: "", 44 expectedOffset: 4, 45 expectedError: &DomainCompressionError{}, 46 }, 47 { 48 name: "Truncated input", 49 input: []byte{3, 'w', 'w'}, 50 expectedDomain: "", 51 expectedOffset: 3, 52 expectedError: &BufferOverflowError{Length: 3, Offset: 4}, 53 }, 54 } 55 56 for _, tt := range tests { 57 t.Run(tt.name, func(t *testing.T) { 58 domain, offset, err := decode_domain(tt.input, tt.offset) 59 60 t.Log(tt.name) 61 assert.Equal(t, tt.expectedError, err) 62 assert.Equal(t, tt.expectedDomain, domain) 63 assert.Equal(t, tt.expectedOffset, offset) 64 }) 65 } 66} 67 68func TestEncodeDomain(t *testing.T) { 69 tests := []struct { 70 name string 71 input string 72 offsets map[string]uint16 73 expected []byte 74 newOffsets map[string]uint16 75 }{ 76 { 77 name: "Simple domain", 78 input: "example.com", 79 offsets: make(map[string]uint16), 80 expected: []byte{7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0}, 81 newOffsets: map[string]uint16{"example.com": 0, "com": 8}, 82 }, 83 { 84 name: "Domain with existing offset", 85 input: "test.example.com", 86 offsets: map[string]uint16{"example.com": 10}, 87 expected: []byte{4, 't', 'e', 's', 't', 0xC0, 0x0A}, 88 newOffsets: map[string]uint16{"test.example.com": 0, "example.com": 10}, 89 }, 90 { 91 name: "Multiple subdomains", 92 input: "a.b.c.d", 93 offsets: make(map[string]uint16), 94 expected: []byte{1, 'a', 1, 'b', 1, 'c', 1, 'd', 0}, 95 newOffsets: map[string]uint16{"a.b.c.d": 0, "b.c.d": 2, "c.d": 4, "d": 6}, 96 }, 97 } 98 99 for _, tt := range tests { 100 t.Run(tt.name, func(t *testing.T) { 101 result := encode_domain([]byte{}, tt.input, &tt.offsets) 102 assert.Equal(t, tt.expected, result, "Encoded domain does not match expected output") 103 assert.Equal(t, tt.newOffsets, tt.offsets, "Offsets map does not match expected state") 104 }) 105 } 106} 107 108func FuzzDecodeDomain(f *testing.F) { 109 testcases := [][]byte{ 110 { 111 0x03, 0x63, 0x6f, 0x6d, 0x00, 112 }, 113 { 114 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x01, 0x63, 0xC0, 0x00, 115 }, 116 { 117 0x03, 0x63, 0x6f, 0x6d, 0xC0, 0x00, 118 }, 119 } 120 for _, tc := range testcases { 121 f.Add(tc) 122 } 123 f.Fuzz(func(t *testing.T, msg []byte) { 124 decode_domain(msg, 0) 125 }) 126}