DNS Stage (#XM2) Write answer section Help

So when I add the code for the Answer Section. I get this error when I run codecrafters test.

[stage-2] Shutting down DNS resolver server...
[stage-2] dns: overflowing header size
[stage-2] This means that the length you have specified in the header of a Record is too long for what followed in the result.
[stage-2] Test failed
[stage-2] Terminating program
[stage-2] Program terminated successfully

Stage 2 doesn’t give an error if I set AnsRecordCount to 0. Stage 4 would error because AnsRecordCount value needs to be 1.

[stage-4] Querying `A` record for codecrafters.io.
[stage-4] Sending Request: (Messages with >>> prefix are part of this log)
[stage-4] >>> ;; opcode: QUERY, status: NOERROR, id: 1234
[stage-4] >>> ;; flags: rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
[stage-4] >>> 
[stage-4] >>> ;; QUESTION SECTION:
[stage-4] >>> ;codecrafters.io. IN       A
[stage-4] >>> 
[stage-4] Received Response: (Messages with >>> prefix are part of this log)
[stage-4] >>> ;; opcode: QUERY, status: NOERROR, id: 1234
[stage-4] >>> ;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
[stage-4] >>> 
[stage-4] >>> ;; QUESTION SECTION:
[stage-4] >>> ;codecrafters.io. IN       A
[stage-4] >>> 
[stage-4] Expected answer section to have one entry got 0
[stage-4] If you have answer set in answer section and are still seeing this error, make sure that you are setting the ANCOUNT to 1 in the header section too.
[stage-4] Test failed
[stage-4] Terminating program
[stage-4] Shutting down DNS resolver server...
[your_program] Received 33 bytes from 127.0.0.1:38897: �

I can’t seem to figure out what’s wrong. Below are my changes:

 func (msg Message) Bytes() []byte {
@@ -12,12 +13,16 @@ func (msg Message) Bytes() []byte {
                res = append(res, question.Bytes()...)
        }
 
+       for _, ans := range msg.answers {
+               res = append(res, ans.Bytes()...)
+       }
+
        return res
 }
 
 func NewMessage() *Message {
        return &Message{
-               &DNSHeader{
+               DNSHeader{
                        PacketID:              1234,
                        QueryRespIndicator:    1,
                        OpCode:                0,
@@ -32,12 +37,25 @@ func NewMessage() *Message {
                        AuthorityRecordCount:  0,
                        AdditionalRecordCount: 0,
                },
-               []*DNSQuestion{
+               []DNSQuestion{
                        {
                                Name:  []byte("\x0ccodecrafters\x02io"),
                                Type:  1,
                                Class: 1,
                        },
                },
+               []DNSAnswer{
+                       {
+                               Name: []DomainLabel{
+                                       {Name: "codecrafters", Len: 12},
+                                       {Name: "io", Len: 2},
+                               },
+                               Type:       1,
+                               Class:      1,
+                               TimeToLive: 60,
+                               Len:        4,
+                               Data:       []byte{1, 1, 1, 1},
+                       },
+               },
        }
 }

File answer.go

type DNSAnswer struct {
    Name       LabelSequence
    Type       uint8
    Class      uint8
    TimeToLive uint8
    Len        uint8
    Data       []byte
}

func (ans DNSAnswer) Bytes() []byte {
    ansName := ans.Name.Bytes()

    ansType := make([]byte, 2)
    binary.BigEndian.PutUint16(ansType, uint16(ans.Type))

    ansClass := make([]byte, 2)
    binary.BigEndian.PutUint16(ansClass, uint16(ans.Class))

    ansTTL := make([]byte, 4)
    binary.BigEndian.PutUint16(ansTTL, uint16(ans.TimeToLive))

    ansLen := make([]byte, 2)
    binary.BigEndian.PutUint16(ansLen, uint16(ans.Len))

    return combineBytes(ansName, ansType, ansClass, ansTTL, ansLen)
}

type DomainLabel struct {
    Name string
    Len  uint8
}

type LabelSequence []DomainLabel

func (label LabelSequence) Bytes() []byte {
    qName := make([]byte, 0)

    for _, l := range label {
        qName = append(qName, l.Len)
        qName = append(qName, []byte(l.Name)...)
    }
    qName = append(qName, 0)

    return qName
}

Would appreciate help :slight_smile:

Note: I’ve updated the title of this post to include the stage ID (#XM2). You can learn about the stages rename here: Upcoming change: Stages overhaul

@Delta456 I haven’t actually tested this, but one thing I noticed:

binary.BigEndian.PutUint16(ansTTL, uint16(ans.TimeToLive))

TTL is 4 bytes, shouldn’t this be PutUint32? Also, the DNSAnswer struct seems to hold uint8 for a lot of the values, which is incorrect too - this should be uint16/uint16 depending on the field.